diff options
| -rw-r--r-- | include/net/netdev_queues.h | 10 | ||||
| -rw-r--r-- | net/core/dev.h | 5 | ||||
| -rw-r--r-- | net/core/netdev_config.c | 64 | ||||
| -rw-r--r-- | 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; } |
