From: Jakub Kicinski <kuba@kernel.org>
To: davem@davemloft.net
Cc: netdev@vger.kernel.org, edumazet@google.com, pabeni@redhat.com,
andrew+netdev@lunn.ch, horms@kernel.org,
michael.chan@broadcom.com, sdf@fomichev.me,
almasrymina@google.com, dtatulea@nvidia.com,
asml.silence@gmail.com, dw@davidwei.uk, daniel@iogearbox.net,
Jakub Kicinski <kuba@kernel.org>
Subject: [PATCH net-next 5/6] net: add queue config validation callback
Date: Wed, 21 Jan 2026 16:51:12 -0800 [thread overview]
Message-ID: <20260122005113.2476634-6-kuba@kernel.org> (raw)
In-Reply-To: <20260122005113.2476634-1-kuba@kernel.org>
I imagine (tm) that as the number of per-queue configuration
options grows some of them may conflict for certain drivers.
While the drivers can obviously do all the validation locally
doing so is fairly inconvenient as the config is fed to drivers
piecemeal via different ops (for different params and NIC-wide
vs per-queue).
Add a centralized callback for validating the queue config
in queue ops. The callback gets invoked before memory provider
is installed, and in the future should also be called when ring
params are modified.
The validation is done after each layer of configuration.
Since we can't fail MP un-binding we must make sure that
the config is valid both before and after MP overrides are
applied. This is moot for now since the set of MP and device
configs are disjoint. It will matter significantly in the future,
so adding it now so that we don't forget..
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
include/net/netdev_queues.h | 10 ++++++
net/core/dev.h | 5 +++
net/core/netdev_config.c | 64 ++++++++++++++++++++++++++++++-------
net/core/netdev_rx_queue.c | 11 +++++--
4 files changed, 76 insertions(+), 14 deletions(-)
diff --git a/include/net/netdev_queues.h b/include/net/netdev_queues.h
index 4b23c3697cc9..95ed28212f4e 100644
--- a/include/net/netdev_queues.h
+++ b/include/net/netdev_queues.h
@@ -143,6 +143,13 @@ enum {
* Queue config structs are passed to this helper before
* the user-requested settings are applied.
*
+ * @ndo_validate_qcfg: (Optional) Check if queue config is supported.
+ * Called when configuration affecting a queue may be
+ * changing, either due to NIC-wide config, or config
+ * scoped to the queue at a specified index.
+ * When NIC-wide config is changed the callback will
+ * be invoked for all queues.
+ *
* @supported_params: Bitmask of supported parameters, see QCFG_*.
*
* Note that @ndo_queue_mem_alloc and @ndo_queue_mem_free may be called while
@@ -166,6 +173,9 @@ struct netdev_queue_mgmt_ops {
int idx);
void (*ndo_default_qcfg)(struct net_device *dev,
struct netdev_queue_config *qcfg);
+ int (*ndo_validate_qcfg)(struct net_device *dev,
+ struct netdev_queue_config *qcfg,
+ struct netlink_ext_ack *extack);
struct device * (*ndo_queue_get_dma_dev)(struct net_device *dev,
int idx);
diff --git a/net/core/dev.h b/net/core/dev.h
index da18536cbd35..98793a738f43 100644
--- a/net/core/dev.h
+++ b/net/core/dev.h
@@ -10,6 +10,7 @@
struct net;
struct netlink_ext_ack;
+struct netdev_queue_config;
struct cpumask;
/* Random bits of netdevice that don't need to be exposed */
@@ -91,6 +92,10 @@ extern struct rw_semaphore dev_addr_sem;
extern struct list_head net_todo_list;
void netdev_run_todo(void);
+int netdev_queue_config_validate(struct net_device *dev, int rxq_idx,
+ struct netdev_queue_config *qcfg,
+ struct netlink_ext_ack *extack);
+
/* netdev management, shared between various uAPI entry points */
struct netdev_name_node {
struct hlist_node hlist;
diff --git a/net/core/netdev_config.c b/net/core/netdev_config.c
index 48f763446506..f14af365d5cd 100644
--- a/net/core/netdev_config.c
+++ b/net/core/netdev_config.c
@@ -4,6 +4,50 @@
#include <net/netdev_queues.h>
#include <net/netdev_rx_queue.h>
+#include "dev.h"
+
+static int netdev_nop_validate_qcfg(struct net_device *dev,
+ struct netdev_queue_config *qcfg,
+ struct netlink_ext_ack *extack)
+{
+ return 0;
+}
+
+static int __netdev_queue_config(struct net_device *dev, int rxq_idx,
+ struct netdev_queue_config *qcfg,
+ struct netlink_ext_ack *extack,
+ bool validate)
+{
+ int (*validate_cb)(struct net_device *dev,
+ struct netdev_queue_config *qcfg,
+ struct netlink_ext_ack *extack);
+ struct pp_memory_provider_params *mpp;
+ int err;
+
+ validate_cb = netdev_nop_validate_qcfg;
+ if (validate && dev->queue_mgmt_ops->ndo_validate_qcfg)
+ validate_cb = dev->queue_mgmt_ops->ndo_validate_qcfg;
+
+ memset(qcfg, 0, sizeof(*qcfg));
+
+ /* Get defaults from the driver, in case user config not set */
+ if (dev->queue_mgmt_ops->ndo_default_qcfg)
+ dev->queue_mgmt_ops->ndo_default_qcfg(dev, qcfg);
+ err = validate_cb(dev, qcfg, extack);
+ if (err)
+ return err;
+
+ /* Apply MP overrides */
+ mpp = &__netif_get_rx_queue(dev, rxq_idx)->mp_params;
+ if (mpp->rx_page_size)
+ qcfg->rx_page_size = mpp->rx_page_size;
+ err = validate_cb(dev, qcfg, extack);
+ if (err)
+ return err;
+
+ return 0;
+}
+
/**
* netdev_queue_config() - get configuration for a given queue
* @dev: net_device instance
@@ -22,17 +66,13 @@
void netdev_queue_config(struct net_device *dev, int rxq_idx,
struct netdev_queue_config *qcfg)
{
- struct pp_memory_provider_params *mpp;
-
- memset(qcfg, 0, sizeof(*qcfg));
-
- /* Get defaults from the driver, in case user config not set */
- if (dev->queue_mgmt_ops->ndo_default_qcfg)
- dev->queue_mgmt_ops->ndo_default_qcfg(dev, qcfg);
-
- /* Apply MP overrides */
- mpp = &__netif_get_rx_queue(dev, rxq_idx)->mp_params;
- if (mpp->rx_page_size)
- qcfg->rx_page_size = mpp->rx_page_size;
+ __netdev_queue_config(dev, rxq_idx, qcfg, NULL, false);
}
EXPORT_SYMBOL(netdev_queue_config);
+
+int netdev_queue_config_validate(struct net_device *dev, int rxq_idx,
+ struct netdev_queue_config *qcfg,
+ struct netlink_ext_ack *extack)
+{
+ return __netdev_queue_config(dev, rxq_idx, qcfg, extack, true);
+}
diff --git a/net/core/netdev_rx_queue.c b/net/core/netdev_rx_queue.c
index 72374930699a..668a90658f25 100644
--- a/net/core/netdev_rx_queue.c
+++ b/net/core/netdev_rx_queue.c
@@ -7,6 +7,7 @@
#include <net/netdev_rx_queue.h>
#include <net/page_pool/memory_provider.h>
+#include "dev.h"
#include "page_pool_priv.h"
/* See also page_pool_is_unreadable() */
@@ -156,12 +157,18 @@ int __net_mp_open_rxq(struct net_device *dev, unsigned int rxq_idx,
netdev_queue_config(dev, rxq_idx, &qcfg[0]);
rxq->mp_params = *p;
- netdev_queue_config(dev, rxq_idx, &qcfg[1]);
+ ret = netdev_queue_config_validate(dev, rxq_idx, &qcfg[1], extack);
+ if (ret)
+ goto err_clear_mp;
ret = netdev_rx_queue_reconfig(dev, rxq_idx, &qcfg[0], &qcfg[1]);
if (ret)
- memset(&rxq->mp_params, 0, sizeof(rxq->mp_params));
+ goto err_clear_mp;
+ return 0;
+
+err_clear_mp:
+ memset(&rxq->mp_params, 0, sizeof(rxq->mp_params));
return ret;
}
--
2.52.0
next prev parent reply other threads:[~2026-01-22 0:51 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-01-22 0:51 [PATCH net-next 0/6] net: restore the structure of driver-facing qcfg API Jakub Kicinski
2026-01-22 0:51 ` [PATCH net-next 1/6] eth: bnxt: always set the queue mgmt ops Jakub Kicinski
2026-01-22 8:04 ` Subbaraya Sundeep
2026-01-22 15:36 ` Jakub Kicinski
2026-01-22 16:31 ` Subbaraya Sundeep
2026-01-22 0:51 ` [PATCH net-next 2/6] net: introduce a trivial netdev_queue_config() Jakub Kicinski
2026-01-22 8:12 ` Subbaraya Sundeep
2026-01-22 15:36 ` Jakub Kicinski
2026-01-22 0:51 ` [PATCH net-next 3/6] net: move mp->rx_page_size validation to __net_mp_open_rxq() Jakub Kicinski
2026-01-22 0:51 ` [PATCH net-next 4/6] net: use netdev_queue_config() for mp restart Jakub Kicinski
2026-01-22 15:06 ` Dragos Tatulea
2026-01-22 15:46 ` Jakub Kicinski
2026-01-22 16:28 ` Dragos Tatulea
2026-01-23 1:41 ` Jakub Kicinski
2026-01-22 0:51 ` Jakub Kicinski [this message]
2026-01-22 0:51 ` [PATCH net-next 6/6] eth: bnxt: plug bnxt_validate_qcfg() into qops Jakub Kicinski
2026-01-23 21:20 ` [PATCH net-next 0/6] net: restore the structure of driver-facing qcfg API patchwork-bot+netdevbpf
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=20260122005113.2476634-6-kuba@kernel.org \
--to=kuba@kernel.org \
--cc=almasrymina@google.com \
--cc=andrew+netdev@lunn.ch \
--cc=asml.silence@gmail.com \
--cc=daniel@iogearbox.net \
--cc=davem@davemloft.net \
--cc=dtatulea@nvidia.com \
--cc=dw@davidwei.uk \
--cc=edumazet@google.com \
--cc=horms@kernel.org \
--cc=michael.chan@broadcom.com \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=sdf@fomichev.me \
/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