From: Joshua Washington <joshwash@google.com>
To: Joshua Washington <joshwash@google.com>,
Anatoly Burakov <anatoly.burakov@intel.com>
Cc: dev@dpdk.org, blasko@google.com, jtranoleary@google.com
Subject: [PATCH v3 2/8] net/gve: refactor ethdev for control ops interface
Date: Fri, 9 Oct 2026 17:59:34 -0700 [thread overview]
Message-ID: <20261010005942.560881-3-joshwash@google.com> (raw)
In-Reply-To: <20261010005942.560881-1-joshwash@google.com>
From: Mark Blasko <blasko@google.com>
Abstract control plane operations into a control operations interface.
This decouples the core driver logic from the AQ implementation.
Store the ops table pointer in a per-process struct gve_process_private
attached to eth_dev->process_private instead of in struct gve_priv:
dev_private is shared with secondary processes, which may map the
driver at a different address. Functions that only have struct gve_priv
look up their ethdev through a new port_id field.
Align AdminQ function parameters to match control operations signatures:
- gve_adminq_configure_device_resources(): read counter array and IRQ
doorbell DMA addresses/counts directly from struct gve_priv (wired to
the get_interrupt_dbs control op).
- gve_adminq_get_ptype_map_dqo(): populate priv->ptype_lut_dqo directly
from struct gve_priv (wired to the get_ptype_map control op).
Move the AdminQ driver compatibility check from gve_init_priv() into
gve_adminq_get_device_properties(). Since gve_init_priv() skips
get_device_properties on device reset, the check now only runs at probe
time and is no longer repeated after a reset.
Move the max_tx_queues and max_rx_queues register reads from
gve_dev_init() into gve_adminq_get_device_properties(), as maximum
queue counts are retrieved via get_device_properties in mailbox mode.
Signed-off-by: Mark Blasko <blasko@google.com>
Signed-off-by: Joshua Washington <joshwash@google.com>
---
v3:
- Store the control ops table pointer in eth_dev->process_private
(struct gve_process_private) instead of in dev_private, which is
shared with secondary processes. Add port_id to struct gve_priv so
functions that only have priv can reach it.
- Mention in the commit message that the driver compatibility check no
longer runs on device reset.
- Only mark query_rss as optional and drop the set_mtu NULL check.
---
drivers/net/gve/base/gve_adminq.c | 18 ++--
drivers/net/gve/base/gve_adminq.h | 9 +-
drivers/net/gve/gve_ethdev.c | 163 ++++++++++++++++++++++--------
drivers/net/gve/gve_ethdev.h | 41 ++++++++
drivers/net/gve/gve_flow_rule.c | 11 +-
drivers/net/gve/gve_rx.c | 3 +-
drivers/net/gve/gve_rx_dqo.c | 3 +-
drivers/net/gve/gve_tx.c | 3 +-
drivers/net/gve/gve_tx_dqo.c | 3 +-
9 files changed, 186 insertions(+), 68 deletions(-)
diff --git a/drivers/net/gve/base/gve_adminq.c b/drivers/net/gve/base/gve_adminq.c
index 89bf669c24..74b9a0125c 100644
--- a/drivers/net/gve/base/gve_adminq.c
+++ b/drivers/net/gve/base/gve_adminq.c
@@ -664,11 +664,7 @@ int gve_adminq_report_nic_timestamp(struct gve_priv *priv, dma_addr_t nic_ts_rep
* gve arranges the msix vectors so that the management vector is last.
*/
#define GVE_NTFY_BLK_BASE_MSIX_IDX 0
-int gve_adminq_configure_device_resources(struct gve_priv *priv,
- dma_addr_t counter_array_bus_addr,
- u32 num_counters,
- dma_addr_t db_array_bus_addr,
- u32 num_ntfy_blks)
+int gve_adminq_configure_device_resources(struct gve_priv *priv)
{
union gve_adminq_command cmd;
@@ -676,10 +672,10 @@ int gve_adminq_configure_device_resources(struct gve_priv *priv,
cmd.opcode = cpu_to_be32(GVE_ADMINQ_CONFIGURE_DEVICE_RESOURCES);
cmd.configure_device_resources =
(struct gve_adminq_configure_device_resources) {
- .counter_array = cpu_to_be64(counter_array_bus_addr),
- .num_counters = cpu_to_be32(num_counters),
- .irq_db_addr = cpu_to_be64(db_array_bus_addr),
- .num_irq_dbs = cpu_to_be32(num_ntfy_blks),
+ .counter_array = cpu_to_be64(priv->cnt_array_mz->iova),
+ .num_counters = cpu_to_be32(priv->num_event_counters),
+ .irq_db_addr = cpu_to_be64(priv->irq_dbs_mz->iova),
+ .num_irq_dbs = cpu_to_be32(priv->num_ntfy_blks),
.irq_db_stride = cpu_to_be32(sizeof(*priv->irq_dbs)),
.ntfy_blk_msix_base_idx =
cpu_to_be32(GVE_NTFY_BLK_BASE_MSIX_IDX),
@@ -1198,9 +1194,9 @@ int gve_adminq_report_link_speed(struct gve_priv *priv)
return err;
}
-int gve_adminq_get_ptype_map_dqo(struct gve_priv *priv,
- struct gve_ptype_lut *ptype_lut)
+int gve_adminq_get_ptype_map_dqo(struct gve_priv *priv)
{
+ struct gve_ptype_lut *ptype_lut = priv->ptype_lut_dqo;
struct gve_dma_mem ptype_map_dma_mem;
struct gve_ptype_map *ptype_map;
union gve_adminq_command cmd;
diff --git a/drivers/net/gve/base/gve_adminq.h b/drivers/net/gve/base/gve_adminq.h
index 954be39fbf..5002cdf783 100644
--- a/drivers/net/gve/base/gve_adminq.h
+++ b/drivers/net/gve/base/gve_adminq.h
@@ -523,11 +523,7 @@ int gve_adminq_alloc(struct gve_priv *priv);
void gve_adminq_free(struct gve_priv *priv);
void gve_adminq_release(struct gve_priv *priv);
int gve_adminq_describe_device(struct gve_priv *priv);
-int gve_adminq_configure_device_resources(struct gve_priv *priv,
- dma_addr_t counter_array_bus_addr,
- u32 num_counters,
- dma_addr_t db_array_bus_addr,
- u32 num_ntfy_blks);
+int gve_adminq_configure_device_resources(struct gve_priv *priv);
int gve_adminq_deconfigure_device_resources(struct gve_priv *priv);
int gve_adminq_create_tx_queues(struct gve_priv *priv, u32 num_queues);
int gve_adminq_destroy_tx_queues(struct gve_priv *priv, u32 queue_id);
@@ -542,8 +538,7 @@ int gve_adminq_report_stats(struct gve_priv *priv, u64 stats_report_len,
int gve_adminq_report_link_speed(struct gve_priv *priv);
struct gve_ptype_lut;
-int gve_adminq_get_ptype_map_dqo(struct gve_priv *priv,
- struct gve_ptype_lut *ptype_lut);
+int gve_adminq_get_ptype_map_dqo(struct gve_priv *priv);
int gve_adminq_verify_driver_compatibility(struct gve_priv *priv,
u64 driver_info_len,
diff --git a/drivers/net/gve/gve_ethdev.c b/drivers/net/gve/gve_ethdev.c
index 80623979a8..ecf4247c19 100644
--- a/drivers/net/gve/gve_ethdev.c
+++ b/drivers/net/gve/gve_ethdev.c
@@ -153,10 +153,13 @@ gve_setup_queue_page_list(struct gve_priv *priv, uint16_t queue_id, bool is_rx,
uint32_t num_pages)
{
const char *queue_type_string = is_rx ? "rx" : "tx";
+ struct gve_process_private *process_priv;
char qpl_name[RTE_MEMZONE_NAMESIZE];
struct gve_queue_page_list *qpl;
int err;
+ process_priv = rte_eth_devices[priv->port_id].process_private;
+
/* Allocate a new QPL. */
snprintf(qpl_name, sizeof(qpl_name), "gve_%s_%s_qpl%d",
priv->pci_dev->device.name, queue_type_string, queue_id);
@@ -181,7 +184,7 @@ gve_setup_queue_page_list(struct gve_priv *priv, uint16_t queue_id, bool is_rx,
priv->max_registered_pages);
goto cleanup_qpl;
}
- err = gve_adminq_register_page_list(priv, qpl);
+ err = process_priv->ctrl_ops->register_page_list(priv, qpl);
if (err) {
PMD_DRV_LOG(ERR,
"Failed to register %s qpl for queue %hu.",
@@ -200,7 +203,11 @@ int
gve_teardown_queue_page_list(struct gve_priv *priv,
struct gve_queue_page_list *qpl)
{
- int err = gve_adminq_unregister_page_list(priv, qpl->id);
+ struct gve_process_private *process_priv;
+ int err;
+
+ process_priv = rte_eth_devices[priv->port_id].process_private;
+ err = process_priv->ctrl_ops->unregister_page_list(priv, qpl->id);
if (err) {
PMD_DRV_LOG(CRIT, "Unable to unregister qpl %d!", qpl->id);
return err;
@@ -213,6 +220,7 @@ gve_teardown_queue_page_list(struct gve_priv *priv,
static int
gve_dev_configure(struct rte_eth_dev *dev)
{
+ struct gve_process_private *process_priv = dev->process_private;
struct gve_priv *priv = dev->data->dev_private;
int err;
@@ -239,7 +247,7 @@ gve_dev_configure(struct rte_eth_dev *dev)
gve_init_rss_config_from_priv(priv, &update_reta_config);
gve_generate_rss_reta(dev, &update_reta_config);
- err = gve_adminq_configure_rss(priv, &update_reta_config);
+ err = process_priv->ctrl_ops->configure_rss(priv, &update_reta_config);
if (err)
PMD_DRV_LOG(ERR,
"Could not reconfigure RSS redirection table.");
@@ -256,6 +264,7 @@ gve_dev_configure(struct rte_eth_dev *dev)
static int
gve_link_update(struct rte_eth_dev *dev, __rte_unused int wait_to_complete)
{
+ struct gve_process_private *process_priv = dev->process_private;
struct gve_priv *priv = dev->data->dev_private;
struct rte_eth_link link;
int err;
@@ -270,7 +279,7 @@ gve_link_update(struct rte_eth_dev *dev, __rte_unused int wait_to_complete)
} else {
link.link_status = RTE_ETH_LINK_UP;
PMD_DRV_LOG(DEBUG, "Get link status from hw");
- err = gve_adminq_report_link_speed(priv);
+ err = process_priv->ctrl_ops->report_link_speed(priv);
if (err) {
PMD_DRV_LOG(ERR, "Failed to get link speed.");
priv->link_speed = RTE_ETH_SPEED_NUM_UNKNOWN;
@@ -359,6 +368,7 @@ gve_get_imissed_from_nic(struct rte_eth_dev *dev)
static int
gve_start_queues(struct rte_eth_dev *dev)
{
+ struct gve_process_private *process_priv = dev->process_private;
struct gve_priv *priv = dev->data->dev_private;
uint16_t num_queues;
uint16_t i;
@@ -366,7 +376,7 @@ gve_start_queues(struct rte_eth_dev *dev)
num_queues = dev->data->nb_tx_queues;
priv->txqs = (struct gve_tx_queue **)dev->data->tx_queues;
- ret = gve_adminq_create_tx_queues(priv, num_queues);
+ ret = process_priv->ctrl_ops->create_tx_queues(priv, num_queues);
if (ret != 0) {
PMD_DRV_LOG(ERR, "Failed to create %u tx queues.", num_queues);
return ret;
@@ -384,7 +394,7 @@ gve_start_queues(struct rte_eth_dev *dev)
num_queues = dev->data->nb_rx_queues;
priv->rxqs = (struct gve_rx_queue **)dev->data->rx_queues;
- ret = gve_adminq_create_rx_queues(priv, num_queues);
+ ret = process_priv->ctrl_ops->create_rx_queues(priv, num_queues);
if (ret != 0) {
PMD_DRV_LOG(ERR, "Failed to create %u rx queues.", num_queues);
goto err_tx;
@@ -422,6 +432,7 @@ gve_start_queues(struct rte_eth_dev *dev)
static int
gve_dev_start(struct rte_eth_dev *dev)
{
+ struct gve_process_private *process_priv = dev->process_private;
struct gve_priv *priv;
int ret;
@@ -450,11 +461,12 @@ gve_dev_start(struct rte_eth_dev *dev)
"Failed to allocate region for stats reporting.");
return ret;
}
- ret = gve_adminq_report_stats(priv, priv->stats_report_len,
+ ret = process_priv->ctrl_ops->setup_stats_report(priv,
+ priv->stats_report_len,
priv->stats_report_mem->iova,
GVE_STATS_REPORT_TIMER_PERIOD);
if (ret != 0) {
- PMD_DRV_LOG(ERR, "gve_adminq_report_stats command failed.");
+ PMD_DRV_LOG(ERR, "setup_stats_report command failed.");
return ret;
}
}
@@ -467,6 +479,7 @@ gve_dev_start(struct rte_eth_dev *dev)
static void
gve_read_nic_clock(void *arg)
{
+ struct gve_process_private *process_priv;
struct gve_priv *priv = arg;
uint32_t fails;
uint64_t ts;
@@ -475,10 +488,12 @@ gve_read_nic_clock(void *arg)
if (!priv || !priv->nic_ts_report_mz)
return;
+ process_priv = rte_eth_devices[priv->port_id].process_private;
+
pthread_mutex_lock(&priv->nic_ts_lock);
memset(priv->nic_ts_report, 0, sizeof(struct gve_nic_ts_report));
- err = gve_adminq_report_nic_timestamp(priv, priv->nic_ts_report_mz->iova);
+ err = process_priv->ctrl_ops->report_nic_timestamp(priv, priv->nic_ts_report_mz->iova);
if (err == 0) {
ts = be64_to_cpu(priv->nic_ts_report->nic_timestamp);
pthread_mutex_unlock(&priv->nic_ts_lock);
@@ -678,11 +693,14 @@ gve_teardown_flow_subsystem(struct gve_priv *priv)
static void
gve_teardown_device_resources(struct gve_priv *priv)
{
+ struct gve_process_private *process_priv;
int err;
+ process_priv = rte_eth_devices[priv->port_id].process_private;
+
/* Tell device its resources are being freed */
if (gve_get_device_resources_ok(priv)) {
- err = gve_adminq_deconfigure_device_resources(priv);
+ err = process_priv->ctrl_ops->free_db_resources(priv);
if (err)
PMD_DRV_LOG(ERR,
"Could not deconfigure device resources: err=%d",
@@ -706,11 +724,15 @@ gve_teardown_device_resources(struct gve_priv *priv)
static int
gve_dev_close(struct rte_eth_dev *dev)
{
+ struct gve_process_private *process_priv = dev->process_private;
struct gve_priv *priv = dev->data->dev_private;
int err = 0;
- if (rte_eal_process_type() != RTE_PROC_PRIMARY)
+ if (rte_eal_process_type() != RTE_PROC_PRIMARY) {
+ free(dev->process_private);
+ dev->process_private = NULL;
return 0;
+ }
if (dev->data->dev_started) {
err = gve_dev_stop(dev);
@@ -723,19 +745,23 @@ gve_dev_close(struct rte_eth_dev *dev)
gve_free_queues(dev);
gve_teardown_device_resources(priv);
- gve_adminq_free(priv);
+ process_priv->ctrl_ops->free_ctrl_plane(priv);
pthread_mutex_destroy(&priv->flow_rule_lock);
pthread_mutex_destroy(&priv->nic_ts_lock);
dev->data->mac_addrs = NULL;
+ free(dev->process_private);
+ dev->process_private = NULL;
+
return err;
}
static int
gve_dev_reset(struct rte_eth_dev *dev)
{
+ struct gve_process_private *process_priv = dev->process_private;
struct gve_priv *priv = dev->data->dev_private;
int err;
@@ -757,7 +783,7 @@ gve_dev_reset(struct rte_eth_dev *dev)
*/
gve_free_queues(dev);
gve_teardown_device_resources(priv);
- gve_adminq_free(priv);
+ process_priv->ctrl_ops->free_ctrl_plane(priv);
err = gve_init_priv(priv, true);
if (err != 0) {
@@ -953,6 +979,7 @@ gve_dev_stats_reset(struct rte_eth_dev *dev)
static int
gve_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu)
{
+ struct gve_process_private *process_priv = dev->process_private;
struct gve_priv *priv = dev->data->dev_private;
int err;
@@ -968,7 +995,7 @@ gve_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu)
return -EBUSY;
}
- err = gve_adminq_set_mtu(priv, mtu);
+ err = process_priv->ctrl_ops->set_mtu(priv, mtu);
if (err) {
PMD_DRV_LOG(ERR, "Failed to set mtu as %u err = %d", mtu, err);
return err;
@@ -1098,6 +1125,7 @@ static int
gve_rss_hash_update(struct rte_eth_dev *dev,
struct rte_eth_rss_conf *rss_conf)
{
+ struct gve_process_private *process_priv = dev->process_private;
struct gve_priv *priv = dev->data->dev_private;
struct gve_rss_config gve_rss_conf;
int rss_reta_size;
@@ -1158,7 +1186,7 @@ gve_rss_hash_update(struct rte_eth_dev *dev,
memcpy(gve_rss_conf.indir, priv->rss_config.indir,
gve_rss_conf.indir_size * sizeof(*priv->rss_config.indir));
- err = gve_adminq_configure_rss(priv, &gve_rss_conf);
+ err = process_priv->ctrl_ops->configure_rss(priv, &gve_rss_conf);
if (!err)
gve_update_priv_rss_config(priv, &gve_rss_conf);
@@ -1198,6 +1226,7 @@ static int
gve_rss_reta_update(struct rte_eth_dev *dev,
struct rte_eth_rss_reta_entry64 *reta_conf, uint16_t reta_size)
{
+ struct gve_process_private *process_priv = dev->process_private;
struct gve_priv *priv = dev->data->dev_private;
struct gve_rss_config gve_rss_conf;
int table_id;
@@ -1234,7 +1263,7 @@ gve_rss_reta_update(struct rte_eth_dev *dev,
table_id++;
}
- err = gve_adminq_configure_rss(priv, &gve_rss_conf);
+ err = process_priv->ctrl_ops->configure_rss(priv, &gve_rss_conf);
if (err)
PMD_DRV_LOG(ERR, "Problem configuring RSS with device.");
else
@@ -1300,6 +1329,7 @@ gve_flow_ops_get(struct rte_eth_dev *dev, const struct rte_flow_ops **ops)
static int
gve_read_clock(struct rte_eth_dev *dev, uint64_t *clock)
{
+ struct gve_process_private *process_priv = dev->process_private;
struct gve_priv *priv = dev->data->dev_private;
uint64_t ts;
int err;
@@ -1311,7 +1341,7 @@ gve_read_clock(struct rte_eth_dev *dev, uint64_t *clock)
return -EIO;
pthread_mutex_lock(&priv->nic_ts_lock);
- err = gve_adminq_report_nic_timestamp(priv, priv->nic_ts_report_mz->iova);
+ err = process_priv->ctrl_ops->report_nic_timestamp(priv, priv->nic_ts_report_mz->iova);
if (err != 0) {
pthread_mutex_unlock(&priv->nic_ts_lock);
return err;
@@ -1428,10 +1458,13 @@ gve_setup_nic_timestamp(struct gve_priv *priv)
static int
gve_setup_device_resources(struct gve_priv *priv)
{
+ struct gve_process_private *process_priv;
char z_name[RTE_MEMZONE_NAMESIZE];
const struct rte_memzone *mz;
int err = 0;
+ process_priv = rte_eth_devices[priv->port_id].process_private;
+
snprintf(z_name, sizeof(z_name), "gve_%s_cnt_arr", priv->pci_dev->device.name);
mz = rte_memzone_reserve_aligned(z_name,
priv->num_event_counters * sizeof(*priv->cnt_array),
@@ -1457,11 +1490,7 @@ gve_setup_device_resources(struct gve_priv *priv)
priv->irq_dbs = (struct gve_irq_db *)mz->addr;
priv->irq_dbs_mz = mz;
- err = gve_adminq_configure_device_resources(priv,
- priv->cnt_array_mz->iova,
- priv->num_event_counters,
- priv->irq_dbs_mz->iova,
- priv->num_ntfy_blks);
+ err = process_priv->ctrl_ops->get_interrupt_dbs(priv);
if (unlikely(err)) {
PMD_DRV_LOG(ERR, "Could not config device resources: err=%d", err);
goto free_irq_dbs;
@@ -1474,7 +1503,7 @@ gve_setup_device_resources(struct gve_priv *priv)
err = -ENOMEM;
goto free_irq_dbs;
}
- err = gve_adminq_get_ptype_map_dqo(priv, priv->ptype_lut_dqo);
+ err = process_priv->ctrl_ops->get_ptype_map(priv);
if (unlikely(err)) {
PMD_DRV_LOG(ERR, "Failed to get ptype map: err=%d", err);
goto free_ptype_lut;
@@ -1563,21 +1592,59 @@ gve_stop_dev_status_polling(struct rte_eth_dev *dev)
}
static int
-gve_init_priv(struct gve_priv *priv, bool skip_describe_device)
+gve_adminq_get_device_properties(struct gve_priv *priv)
{
- int num_ntfy;
int err;
- /* Set up the adminq */
- err = gve_adminq_alloc(priv);
+ err = gve_verify_driver_compatibility(priv);
if (err) {
- PMD_DRV_LOG(ERR, "Failed to alloc admin queue: err=%d", err);
+ PMD_DRV_LOG(ERR, "Could not verify driver compatibility: err=%d", err);
return err;
}
- err = gve_verify_driver_compatibility(priv);
+
+ /* Get max queues to alloc etherdev */
+ priv->max_nb_txq = ioread32be(&priv->reg_bar0->max_tx_queues);
+ priv->max_nb_rxq = ioread32be(&priv->reg_bar0->max_rx_queues);
+
+ return gve_adminq_describe_device(priv);
+}
+
+static const struct gve_ctrl_ops gve_adminq_ops = {
+ .init_ctrl_plane = gve_adminq_alloc,
+ .free_ctrl_plane = gve_adminq_free,
+ .get_device_properties = gve_adminq_get_device_properties,
+ .get_ptype_map = gve_adminq_get_ptype_map_dqo,
+ .get_interrupt_dbs = gve_adminq_configure_device_resources,
+ .create_tx_queues = gve_adminq_create_tx_queues,
+ .destroy_tx_queues = gve_adminq_destroy_tx_queues,
+ .create_rx_queues = gve_adminq_create_rx_queues,
+ .destroy_rx_queues = gve_adminq_destroy_rx_queues,
+ .report_link_speed = gve_adminq_report_link_speed,
+ .configure_rss = gve_adminq_configure_rss,
+ .add_flow_rule = gve_adminq_add_flow_rule,
+ .del_flow_rule = gve_adminq_del_flow_rule,
+ .reset_flow_rules = gve_adminq_reset_flow_rules,
+ .free_db_resources = gve_adminq_deconfigure_device_resources,
+ .setup_stats_report = gve_adminq_report_stats,
+ .report_nic_timestamp = gve_adminq_report_nic_timestamp,
+ .set_mtu = gve_adminq_set_mtu,
+ .register_page_list = gve_adminq_register_page_list,
+ .unregister_page_list = gve_adminq_unregister_page_list,
+};
+
+static int
+gve_init_priv(struct gve_priv *priv, bool skip_describe_device)
+{
+ struct gve_process_private *process_priv;
+ int num_ntfy;
+ int err;
+
+ process_priv = rte_eth_devices[priv->port_id].process_private;
+
+ err = process_priv->ctrl_ops->init_ctrl_plane(priv);
if (err) {
- PMD_DRV_LOG(ERR, "Could not verify driver compatibility: err=%d", err);
- goto free_adminq;
+ PMD_DRV_LOG(ERR, "Failed to alloc control plane: err=%d", err);
+ return err;
}
if (skip_describe_device)
@@ -1587,7 +1654,7 @@ gve_init_priv(struct gve_priv *priv, bool skip_describe_device)
gve_set_default_ring_size_bounds(priv);
/* Get the initial information we need from the device */
- err = gve_adminq_describe_device(priv);
+ err = process_priv->ctrl_ops->get_device_properties(priv);
if (err) {
PMD_DRV_LOG(ERR, "Could not get device information: err=%d", err);
goto free_adminq;
@@ -1637,7 +1704,7 @@ gve_init_priv(struct gve_priv *priv, bool skip_describe_device)
if (!err)
return 0;
free_adminq:
- gve_adminq_free(priv);
+ process_priv->ctrl_ops->free_ctrl_plane(priv);
return err;
}
@@ -1645,13 +1712,21 @@ static int
gve_dev_init(struct rte_eth_dev *eth_dev)
{
struct gve_priv *priv = eth_dev->data->dev_private;
- int max_tx_queues, max_rx_queues;
+ struct gve_process_private *process_priv;
struct rte_pci_device *pci_dev;
struct gve_registers *reg_bar;
pthread_mutexattr_t mutexattr;
rte_be32_t *db_bar;
int err;
+ process_priv = calloc(1, sizeof(struct gve_process_private));
+ if (!process_priv) {
+ PMD_DRV_LOG(ERR, "Failed to alloc process_private");
+ return -ENOMEM;
+ }
+ process_priv->ctrl_ops = &gve_adminq_ops;
+ eth_dev->process_private = process_priv;
+
if (rte_eal_process_type() != RTE_PROC_PRIMARY) {
if (gve_is_gqi(priv)) {
gve_set_rx_function(eth_dev);
@@ -1670,28 +1745,25 @@ gve_dev_init(struct rte_eth_dev *eth_dev)
reg_bar = pci_dev->mem_resource[GVE_REG_BAR].addr;
if (!reg_bar) {
PMD_DRV_LOG(ERR, "Failed to map pci bar!");
- return -ENOMEM;
+ err = -ENOMEM;
+ goto free_process_priv;
}
db_bar = pci_dev->mem_resource[GVE_DB_BAR].addr;
if (!db_bar) {
PMD_DRV_LOG(ERR, "Failed to map doorbell bar!");
- return -ENOMEM;
+ err = -ENOMEM;
+ goto free_process_priv;
}
gve_write_version(®_bar->driver_version);
- /* Get max queues to alloc etherdev */
- max_tx_queues = ioread32be(®_bar->max_tx_queues);
- max_rx_queues = ioread32be(®_bar->max_rx_queues);
priv->reg_bar0 = reg_bar;
priv->db_bar2 = db_bar;
priv->pci_dev = pci_dev;
+ priv->port_id = eth_dev->data->port_id;
priv->state_flags = 0x0;
- priv->max_nb_txq = max_tx_queues;
- priv->max_nb_rxq = max_rx_queues;
-
pthread_mutexattr_init(&mutexattr);
pthread_mutexattr_setpshared(&mutexattr, PTHREAD_PROCESS_SHARED);
pthread_mutex_init(&priv->flow_rule_lock, &mutexattr);
@@ -1703,7 +1775,7 @@ gve_dev_init(struct rte_eth_dev *eth_dev)
if (err) {
pthread_mutex_destroy(&priv->flow_rule_lock);
pthread_mutex_destroy(&priv->nic_ts_lock);
- return err;
+ goto free_process_priv;
}
if (gve_is_gqi(priv)) {
@@ -1719,6 +1791,11 @@ gve_dev_init(struct rte_eth_dev *eth_dev)
eth_dev->data->mac_addrs = &priv->dev_addr;
return 0;
+
+free_process_priv:
+ free(eth_dev->process_private);
+ eth_dev->process_private = NULL;
+ return err;
}
static int
diff --git a/drivers/net/gve/gve_ethdev.h b/drivers/net/gve/gve_ethdev.h
index c9a176ff17..7dbc1753a5 100644
--- a/drivers/net/gve/gve_ethdev.h
+++ b/drivers/net/gve/gve_ethdev.h
@@ -272,6 +272,46 @@ struct gve_flow {
extern const struct rte_flow_ops gve_flow_ops;
+struct gve_priv;
+struct gve_flow_rule_params;
+
+struct gve_ctrl_ops {
+ int (*init_ctrl_plane)(struct gve_priv *priv);
+ void (*free_ctrl_plane)(struct gve_priv *priv);
+ int (*get_device_properties)(struct gve_priv *priv);
+ int (*get_ptype_map)(struct gve_priv *priv);
+ int (*get_interrupt_dbs)(struct gve_priv *priv);
+ int (*create_tx_queues)(struct gve_priv *priv, uint32_t num_queues);
+ int (*destroy_tx_queues)(struct gve_priv *priv, uint32_t num_queues);
+ int (*create_rx_queues)(struct gve_priv *priv, uint32_t num_queues);
+ int (*destroy_rx_queues)(struct gve_priv *priv, uint32_t num_queues);
+ int (*report_link_speed)(struct gve_priv *priv);
+ int (*configure_rss)(struct gve_priv *priv,
+ struct gve_rss_config *rss_conf);
+ int (*add_flow_rule)(struct gve_priv *priv,
+ struct gve_flow_rule_params *rule, uint32_t loc);
+ int (*del_flow_rule)(struct gve_priv *priv, uint32_t loc);
+ int (*reset_flow_rules)(struct gve_priv *priv);
+ int (*free_db_resources)(struct gve_priv *priv);
+ int (*setup_stats_report)(struct gve_priv *priv,
+ uint64_t stats_report_len,
+ dma_addr_t stats_report_addr,
+ uint64_t interval_ms);
+ int (*report_nic_timestamp)(struct gve_priv *priv, dma_addr_t dma_addr);
+ int (*set_mtu)(struct gve_priv *priv, uint64_t mtu);
+ int (*register_page_list)(struct gve_priv *priv,
+ struct gve_queue_page_list *qpl);
+ int (*unregister_page_list)(struct gve_priv *priv,
+ uint32_t page_list_id);
+
+ /* Optional, may be NULL. Callers must check before use. */
+ int (*query_rss)(struct gve_priv *priv);
+};
+
+struct gve_process_private {
+ const struct gve_ctrl_ops *ctrl_ops;
+};
+
struct gve_priv {
struct gve_irq_db *irq_dbs; /* array of num_ntfy_blks */
const struct rte_memzone *irq_dbs_mz;
@@ -310,6 +350,7 @@ struct gve_priv {
struct gve_registers __iomem *reg_bar0; /* see gve_register.h */
rte_be32_t __iomem *db_bar2; /* "array" of doorbells */
struct rte_pci_device *pci_dev;
+ uint16_t port_id;
/* Admin queue - see gve_adminq.h*/
union gve_adminq_command *adminq;
diff --git a/drivers/net/gve/gve_flow_rule.c b/drivers/net/gve/gve_flow_rule.c
index 1266e197ea..aec039c32b 100644
--- a/drivers/net/gve/gve_flow_rule.c
+++ b/drivers/net/gve/gve_flow_rule.c
@@ -446,11 +446,14 @@ gve_flow_free_bmp(struct gve_priv *priv)
int
gve_free_flow_rules(struct gve_priv *priv)
{
+ struct gve_process_private *process_priv;
struct gve_flow *flow;
int err = 0;
+ process_priv = rte_eth_devices[priv->port_id].process_private;
+
if (!TAILQ_EMPTY(&priv->active_flows)) {
- err = gve_adminq_reset_flow_rules(priv);
+ err = process_priv->ctrl_ops->reset_flow_rules(priv);
if (err) {
PMD_DRV_LOG(ERR,
"Failed to reset flow rules, internal device err=%d",
@@ -475,6 +478,7 @@ gve_create_flow_rule(struct rte_eth_dev *dev,
const struct rte_flow_action actions[],
struct rte_flow_error *error)
{
+ struct gve_process_private *process_priv = dev->process_private;
struct gve_priv *priv = dev->data->dev_private;
struct gve_flow_rule_params rule = {0};
uint64_t slab_bits = 0;
@@ -516,7 +520,7 @@ gve_create_flow_rule(struct rte_eth_dev *dev,
goto free_flow_and_unlock;
}
- err = gve_adminq_add_flow_rule(priv, &rule, flow->rule_id);
+ err = process_priv->ctrl_ops->add_flow_rule(priv, &rule, flow->rule_id);
if (err) {
rte_bitmap_set(priv->avail_flow_rule_bmp, flow->rule_id);
rte_flow_error_set(error, -err,
@@ -541,6 +545,7 @@ static int
gve_destroy_flow_rule(struct rte_eth_dev *dev, struct rte_flow *flow_handle,
struct rte_flow_error *error)
{
+ struct gve_process_private *process_priv = dev->process_private;
struct gve_priv *priv = dev->data->dev_private;
struct gve_flow *flow;
bool flow_rule_active;
@@ -588,7 +593,7 @@ gve_destroy_flow_rule(struct rte_eth_dev *dev, struct rte_flow *flow_handle,
goto unlock;
}
- err = gve_adminq_del_flow_rule(priv, flow->rule_id);
+ err = process_priv->ctrl_ops->del_flow_rule(priv, flow->rule_id);
if (err) {
rte_flow_error_set(error, -err,
RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
diff --git a/drivers/net/gve/gve_rx.c b/drivers/net/gve/gve_rx.c
index d14902c662..472d8406ba 100644
--- a/drivers/net/gve/gve_rx.c
+++ b/drivers/net/gve/gve_rx.c
@@ -518,6 +518,7 @@ gve_rx_queue_stop(struct rte_eth_dev *dev, uint16_t rx_queue_id)
void
gve_stop_rx_queues(struct rte_eth_dev *dev)
{
+ struct gve_process_private *process_priv = dev->process_private;
struct gve_priv *hw = dev->data->dev_private;
uint16_t i;
int err;
@@ -525,7 +526,7 @@ gve_stop_rx_queues(struct rte_eth_dev *dev)
if (!gve_is_gqi(hw))
return gve_stop_rx_queues_dqo(dev);
- err = gve_adminq_destroy_rx_queues(hw, dev->data->nb_rx_queues);
+ err = process_priv->ctrl_ops->destroy_rx_queues(hw, dev->data->nb_rx_queues);
if (err != 0)
PMD_DRV_LOG(WARNING, "failed to destroy rxqs");
diff --git a/drivers/net/gve/gve_rx_dqo.c b/drivers/net/gve/gve_rx_dqo.c
index 3665d9e4cd..1f901c5fd4 100644
--- a/drivers/net/gve/gve_rx_dqo.c
+++ b/drivers/net/gve/gve_rx_dqo.c
@@ -556,11 +556,12 @@ gve_rx_queue_stop_dqo(struct rte_eth_dev *dev, uint16_t rx_queue_id)
void
gve_stop_rx_queues_dqo(struct rte_eth_dev *dev)
{
+ struct gve_process_private *process_priv = dev->process_private;
struct gve_priv *hw = dev->data->dev_private;
uint16_t i;
int err;
- err = gve_adminq_destroy_rx_queues(hw, dev->data->nb_rx_queues);
+ err = process_priv->ctrl_ops->destroy_rx_queues(hw, dev->data->nb_rx_queues);
if (err != 0)
PMD_DRV_LOG(WARNING, "failed to destroy rxqs");
diff --git a/drivers/net/gve/gve_tx.c b/drivers/net/gve/gve_tx.c
index c0400b07bf..568e948daa 100644
--- a/drivers/net/gve/gve_tx.c
+++ b/drivers/net/gve/gve_tx.c
@@ -725,6 +725,7 @@ gve_tx_queue_stop(struct rte_eth_dev *dev, uint16_t tx_queue_id)
void
gve_stop_tx_queues(struct rte_eth_dev *dev)
{
+ struct gve_process_private *process_priv = dev->process_private;
struct gve_priv *hw = dev->data->dev_private;
uint16_t i;
int err;
@@ -732,7 +733,7 @@ gve_stop_tx_queues(struct rte_eth_dev *dev)
if (!gve_is_gqi(hw))
return gve_stop_tx_queues_dqo(dev);
- err = gve_adminq_destroy_tx_queues(hw, dev->data->nb_tx_queues);
+ err = process_priv->ctrl_ops->destroy_tx_queues(hw, dev->data->nb_tx_queues);
if (err != 0)
PMD_DRV_LOG(WARNING, "failed to destroy txqs");
diff --git a/drivers/net/gve/gve_tx_dqo.c b/drivers/net/gve/gve_tx_dqo.c
index 5c03d3d1a2..0b4d6074ab 100644
--- a/drivers/net/gve/gve_tx_dqo.c
+++ b/drivers/net/gve/gve_tx_dqo.c
@@ -608,11 +608,12 @@ gve_tx_queue_stop_dqo(struct rte_eth_dev *dev, uint16_t tx_queue_id)
void
gve_stop_tx_queues_dqo(struct rte_eth_dev *dev)
{
+ struct gve_process_private *process_priv = dev->process_private;
struct gve_priv *hw = dev->data->dev_private;
uint16_t i;
int err;
- err = gve_adminq_destroy_tx_queues(hw, dev->data->nb_tx_queues);
+ err = process_priv->ctrl_ops->destroy_tx_queues(hw, dev->data->nb_tx_queues);
if (err != 0)
PMD_DRV_LOG(WARNING, "failed to destroy txqs");
--
2.56.0.170.g584c36229d-goog
next prev parent reply other threads:[~2026-10-10 1:00 UTC|newest]
Thread overview: 32+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-03 2:51 [PATCH 0/8] gve: precursor control plane changes before bare-metal support Joshua Washington
2026-10-03 2:51 ` [PATCH 1/8] net/gve: refactor ethdev for control ops interface Joshua Washington
2026-10-03 2:51 ` [PATCH 2/8] net/gve: rename doorbell BAR variable to be more generic Joshua Washington
2026-10-03 2:51 ` [PATCH 3/8] net/gve: split default queue counts into Tx and Rx Joshua Washington
2026-10-03 2:51 ` [PATCH 4/8] net/gve: clean Tx queue directly in dqo Joshua Washington
2026-10-03 2:51 ` [PATCH 5/8] net/gve: update RSS config just after successful programming Joshua Washington
2026-10-03 2:51 ` [PATCH 6/8] net/gve: add RSS cache boolean flag Joshua Washington
2026-10-03 2:51 ` [PATCH 7/8] net/gve: fix RSS config memory leak on close Joshua Washington
2026-10-03 2:51 ` [PATCH 8/8] net/gve: refactor timestamp support to clock read type Joshua Washington
2026-10-03 16:29 ` [PATCH 0/8] gve: precursor control plane changes before bare-metal support Stephen Hemminger
2026-10-05 19:39 ` [PATCH v2 " Joshua Washington
2026-10-05 19:39 ` [PATCH v2 1/8] net/gve: refactor ethdev for control ops interface Joshua Washington
2026-10-05 19:39 ` [PATCH v2 2/8] net/gve: rename doorbell BAR variable to be more generic Joshua Washington
2026-10-05 19:39 ` [PATCH v2 3/8] net/gve: split default queue counts into Tx and Rx Joshua Washington
2026-10-05 19:39 ` [PATCH v2 4/8] net/gve: clean Tx queue directly in dqo Joshua Washington
2026-10-05 19:39 ` [PATCH v2 5/8] net/gve: update RSS config just after successful programming Joshua Washington
2026-10-05 19:39 ` [PATCH v2 6/8] net/gve: add RSS cache boolean flag Joshua Washington
2026-10-05 19:39 ` [PATCH v2 7/8] net/gve: fix RSS config memory leak on close Joshua Washington
2026-10-05 19:39 ` [PATCH v2 8/8] net/gve: refactor timestamp support to clock read type Joshua Washington
2026-10-06 14:19 ` [PATCH v2 0/8] gve: precursor control plane changes before bare-metal support Stephen Hemminger
2026-10-06 15:10 ` Stephen Hemminger
2026-10-07 20:11 ` Joshua Washington
2026-10-10 0:59 ` [PATCH v3 " Joshua Washington
2026-10-10 0:59 ` [PATCH v3 1/8] net/gve: fix RSS config memory leak on close Joshua Washington
2026-10-10 0:59 ` Joshua Washington [this message]
2026-10-10 0:59 ` [PATCH v3 3/8] net/gve: rename doorbell BAR variable to be more generic Joshua Washington
2026-10-10 0:59 ` [PATCH v3 4/8] net/gve: split default queue counts into Tx and Rx Joshua Washington
2026-10-10 0:59 ` [PATCH v3 5/8] net/gve: clean Tx queue directly in dqo Joshua Washington
2026-10-10 0:59 ` [PATCH v3 6/8] net/gve: update RSS config just after successful programming Joshua Washington
2026-10-10 0:59 ` [PATCH v3 7/8] net/gve: add RSS cache boolean flag Joshua Washington
2026-10-10 0:59 ` [PATCH v3 8/8] net/gve: refactor timestamp support to clock read type Joshua Washington
2026-10-10 18:24 ` [PATCH v3 0/8] gve: precursor control plane changes before bare-metal support Stephen Hemminger
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261010005942.560881-3-joshwash@google.com \
--to=joshwash@google.com \
--cc=anatoly.burakov@intel.com \
--cc=blasko@google.com \
--cc=dev@dpdk.org \
--cc=jtranoleary@google.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox