mirror of
https://github.com/torvalds/linux.git
synced 2026-05-23 06:31:58 +02:00
Merge branch 'net-make-memory-provider-install-close-paths-more-common'
Jakub Kicinski says: ==================== net: make memory provider install / close paths more common We seem to be fixing bugs in config path for devmem which also exist in the io_uring ZC path. Let's try to make the two paths more common, otherwise this is bound to keep happening. Found by code inspection and compile tested only. v1: https://lore.kernel.org/20250331194201.2026422-1-kuba@kernel.org ==================== Link: https://patch.msgid.link/20250403013405.2827250-1-kuba@kernel.org Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
d84366bc5b
|
|
@ -6,6 +6,7 @@
|
|||
#include <net/page_pool/types.h>
|
||||
|
||||
struct netdev_rx_queue;
|
||||
struct netlink_ext_ack;
|
||||
struct sk_buff;
|
||||
|
||||
struct memory_provider_ops {
|
||||
|
|
@ -24,8 +25,13 @@ void net_mp_niov_clear_page_pool(struct net_iov *niov);
|
|||
|
||||
int net_mp_open_rxq(struct net_device *dev, unsigned ifq_idx,
|
||||
struct pp_memory_provider_params *p);
|
||||
int __net_mp_open_rxq(struct net_device *dev, unsigned int rxq_idx,
|
||||
const struct pp_memory_provider_params *p,
|
||||
struct netlink_ext_ack *extack);
|
||||
void net_mp_close_rxq(struct net_device *dev, unsigned ifq_idx,
|
||||
struct pp_memory_provider_params *old_p);
|
||||
void __net_mp_close_rxq(struct net_device *dev, unsigned int rxq_idx,
|
||||
const struct pp_memory_provider_params *old_p);
|
||||
|
||||
/**
|
||||
* net_mp_netmem_place_in_cache() - give a netmem to a page pool
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@
|
|||
*/
|
||||
|
||||
#include <linux/dma-buf.h>
|
||||
#include <linux/ethtool_netlink.h>
|
||||
#include <linux/genalloc.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/netdevice.h>
|
||||
|
|
@ -117,21 +116,19 @@ void net_devmem_unbind_dmabuf(struct net_devmem_dmabuf_binding *binding)
|
|||
struct netdev_rx_queue *rxq;
|
||||
unsigned long xa_idx;
|
||||
unsigned int rxq_idx;
|
||||
int err;
|
||||
|
||||
if (binding->list.next)
|
||||
list_del(&binding->list);
|
||||
|
||||
xa_for_each(&binding->bound_rxqs, xa_idx, rxq) {
|
||||
WARN_ON(rxq->mp_params.mp_priv != binding);
|
||||
|
||||
rxq->mp_params.mp_priv = NULL;
|
||||
rxq->mp_params.mp_ops = NULL;
|
||||
const struct pp_memory_provider_params mp_params = {
|
||||
.mp_priv = binding,
|
||||
.mp_ops = &dmabuf_devmem_ops,
|
||||
};
|
||||
|
||||
rxq_idx = get_netdev_rx_queue_index(rxq);
|
||||
|
||||
err = netdev_rx_queue_restart(binding->dev, rxq_idx);
|
||||
WARN_ON(err && err != -ENETDOWN);
|
||||
__net_mp_close_rxq(binding->dev, rxq_idx, &mp_params);
|
||||
}
|
||||
|
||||
xa_erase(&net_devmem_dmabuf_bindings, binding->id);
|
||||
|
|
@ -143,57 +140,28 @@ int net_devmem_bind_dmabuf_to_queue(struct net_device *dev, u32 rxq_idx,
|
|||
struct net_devmem_dmabuf_binding *binding,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct pp_memory_provider_params mp_params = {
|
||||
.mp_priv = binding,
|
||||
.mp_ops = &dmabuf_devmem_ops,
|
||||
};
|
||||
struct netdev_rx_queue *rxq;
|
||||
u32 xa_idx;
|
||||
int err;
|
||||
|
||||
if (rxq_idx >= dev->real_num_rx_queues) {
|
||||
NL_SET_ERR_MSG(extack, "rx queue index out of range");
|
||||
return -ERANGE;
|
||||
}
|
||||
|
||||
if (dev->cfg->hds_config != ETHTOOL_TCP_DATA_SPLIT_ENABLED) {
|
||||
NL_SET_ERR_MSG(extack, "tcp-data-split is disabled");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (dev->cfg->hds_thresh) {
|
||||
NL_SET_ERR_MSG(extack, "hds-thresh is not zero");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rxq = __netif_get_rx_queue(dev, rxq_idx);
|
||||
if (rxq->mp_params.mp_ops) {
|
||||
NL_SET_ERR_MSG(extack, "designated queue already memory provider bound");
|
||||
return -EEXIST;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_XDP_SOCKETS
|
||||
if (rxq->pool) {
|
||||
NL_SET_ERR_MSG(extack, "designated queue already in use by AF_XDP");
|
||||
return -EBUSY;
|
||||
}
|
||||
#endif
|
||||
|
||||
err = xa_alloc(&binding->bound_rxqs, &xa_idx, rxq, xa_limit_32b,
|
||||
GFP_KERNEL);
|
||||
err = __net_mp_open_rxq(dev, rxq_idx, &mp_params, extack);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
rxq->mp_params.mp_priv = binding;
|
||||
rxq->mp_params.mp_ops = &dmabuf_devmem_ops;
|
||||
|
||||
err = netdev_rx_queue_restart(dev, rxq_idx);
|
||||
rxq = __netif_get_rx_queue(dev, rxq_idx);
|
||||
err = xa_alloc(&binding->bound_rxqs, &xa_idx, rxq, xa_limit_32b,
|
||||
GFP_KERNEL);
|
||||
if (err)
|
||||
goto err_xa_erase;
|
||||
goto err_close_rxq;
|
||||
|
||||
return 0;
|
||||
|
||||
err_xa_erase:
|
||||
rxq->mp_params.mp_priv = NULL;
|
||||
rxq->mp_params.mp_ops = NULL;
|
||||
xa_erase(&binding->bound_rxqs, xa_idx);
|
||||
|
||||
err_close_rxq:
|
||||
__net_mp_close_rxq(dev, rxq_idx, &mp_params);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -874,12 +874,6 @@ int netdev_nl_bind_rx_doit(struct sk_buff *skb, struct genl_info *info)
|
|||
goto err_unlock;
|
||||
}
|
||||
|
||||
if (dev_xdp_prog_count(netdev)) {
|
||||
NL_SET_ERR_MSG(info->extack, "unable to bind dmabuf to device with XDP program attached");
|
||||
err = -EEXIST;
|
||||
goto err_unlock;
|
||||
}
|
||||
|
||||
binding = net_devmem_bind_dmabuf(netdev, dmabuf_fd, info->extack);
|
||||
if (IS_ERR(binding)) {
|
||||
err = PTR_ERR(binding);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <linux/ethtool_netlink.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <net/netdev_lock.h>
|
||||
#include <net/netdev_queues.h>
|
||||
|
|
@ -86,8 +87,9 @@ int netdev_rx_queue_restart(struct net_device *dev, unsigned int rxq_idx)
|
|||
}
|
||||
EXPORT_SYMBOL_NS_GPL(netdev_rx_queue_restart, "NETDEV_INTERNAL");
|
||||
|
||||
static int __net_mp_open_rxq(struct net_device *dev, unsigned ifq_idx,
|
||||
struct pp_memory_provider_params *p)
|
||||
int __net_mp_open_rxq(struct net_device *dev, unsigned int rxq_idx,
|
||||
const struct pp_memory_provider_params *p,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct netdev_rx_queue *rxq;
|
||||
int ret;
|
||||
|
|
@ -95,16 +97,41 @@ static int __net_mp_open_rxq(struct net_device *dev, unsigned ifq_idx,
|
|||
if (!netdev_need_ops_lock(dev))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (ifq_idx >= dev->real_num_rx_queues)
|
||||
if (rxq_idx >= dev->real_num_rx_queues)
|
||||
return -EINVAL;
|
||||
ifq_idx = array_index_nospec(ifq_idx, dev->real_num_rx_queues);
|
||||
rxq_idx = array_index_nospec(rxq_idx, dev->real_num_rx_queues);
|
||||
|
||||
rxq = __netif_get_rx_queue(dev, ifq_idx);
|
||||
if (rxq->mp_params.mp_ops)
|
||||
if (rxq_idx >= dev->real_num_rx_queues) {
|
||||
NL_SET_ERR_MSG(extack, "rx queue index out of range");
|
||||
return -ERANGE;
|
||||
}
|
||||
if (dev->cfg->hds_config != ETHTOOL_TCP_DATA_SPLIT_ENABLED) {
|
||||
NL_SET_ERR_MSG(extack, "tcp-data-split is disabled");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (dev->cfg->hds_thresh) {
|
||||
NL_SET_ERR_MSG(extack, "hds-thresh is not zero");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (dev_xdp_prog_count(dev)) {
|
||||
NL_SET_ERR_MSG(extack, "unable to custom memory provider to device with XDP program attached");
|
||||
return -EEXIST;
|
||||
}
|
||||
|
||||
rxq = __netif_get_rx_queue(dev, rxq_idx);
|
||||
if (rxq->mp_params.mp_ops) {
|
||||
NL_SET_ERR_MSG(extack, "designated queue already memory provider bound");
|
||||
return -EEXIST;
|
||||
}
|
||||
#ifdef CONFIG_XDP_SOCKETS
|
||||
if (rxq->pool) {
|
||||
NL_SET_ERR_MSG(extack, "designated queue already in use by AF_XDP");
|
||||
return -EBUSY;
|
||||
}
|
||||
#endif
|
||||
|
||||
rxq->mp_params = *p;
|
||||
ret = netdev_rx_queue_restart(dev, ifq_idx);
|
||||
ret = netdev_rx_queue_restart(dev, rxq_idx);
|
||||
if (ret) {
|
||||
rxq->mp_params.mp_ops = NULL;
|
||||
rxq->mp_params.mp_priv = NULL;
|
||||
|
|
@ -112,21 +139,22 @@ static int __net_mp_open_rxq(struct net_device *dev, unsigned ifq_idx,
|
|||
return ret;
|
||||
}
|
||||
|
||||
int net_mp_open_rxq(struct net_device *dev, unsigned ifq_idx,
|
||||
int net_mp_open_rxq(struct net_device *dev, unsigned int rxq_idx,
|
||||
struct pp_memory_provider_params *p)
|
||||
{
|
||||
int ret;
|
||||
|
||||
netdev_lock(dev);
|
||||
ret = __net_mp_open_rxq(dev, ifq_idx, p);
|
||||
ret = __net_mp_open_rxq(dev, rxq_idx, p, NULL);
|
||||
netdev_unlock(dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __net_mp_close_rxq(struct net_device *dev, unsigned ifq_idx,
|
||||
struct pp_memory_provider_params *old_p)
|
||||
void __net_mp_close_rxq(struct net_device *dev, unsigned int ifq_idx,
|
||||
const struct pp_memory_provider_params *old_p)
|
||||
{
|
||||
struct netdev_rx_queue *rxq;
|
||||
int err;
|
||||
|
||||
if (WARN_ON_ONCE(ifq_idx >= dev->real_num_rx_queues))
|
||||
return;
|
||||
|
|
@ -146,7 +174,8 @@ static void __net_mp_close_rxq(struct net_device *dev, unsigned ifq_idx,
|
|||
|
||||
rxq->mp_params.mp_ops = NULL;
|
||||
rxq->mp_params.mp_priv = NULL;
|
||||
WARN_ON(netdev_rx_queue_restart(dev, ifq_idx));
|
||||
err = netdev_rx_queue_restart(dev, ifq_idx);
|
||||
WARN_ON(err && err != -ENETDOWN);
|
||||
}
|
||||
|
||||
void net_mp_close_rxq(struct net_device *dev, unsigned ifq_idx,
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user