Thread (27 messages) 27 messages, 6 authors, 2025-10-02

Re: [RFC net-next v3 6/7] net: devmem: pre-read requested rx queues during bind

From: Dragos Tatulea <dtatulea@nvidia.com>
Date: 2025-08-16 08:59:16
Also in: lkml

On Fri, Aug 15, 2025 at 11:05:56AM -0700, Mina Almasry wrote:
On Fri, Aug 15, 2025 at 4:07 AM Dragos Tatulea [off-list ref] wrote:
quoted
Instead of reading the requested rx queues after binding the buffer,
read the rx queues in advance in a bitmap and iterate over them when
needed.

This is a preparation for fetching the DMA device for each queue.

This patch has no functional changes.

Signed-off-by: Dragos Tatulea <dtatulea@nvidia.com>
---
 net/core/netdev-genl.c | 76 +++++++++++++++++++++++++++---------------
 1 file changed, 49 insertions(+), 27 deletions(-)
diff --git a/net/core/netdev-genl.c b/net/core/netdev-genl.c
index 3e2d6aa6e060..3e990f100bf0 100644
--- a/net/core/netdev-genl.c
+++ b/net/core/netdev-genl.c
@@ -869,17 +869,50 @@ int netdev_nl_qstats_get_dumpit(struct sk_buff *skb,
        return err;
 }

-int netdev_nl_bind_rx_doit(struct sk_buff *skb, struct genl_info *info)
+static int netdev_nl_read_rxq_bitmap(struct genl_info *info,
+                                    unsigned long *rxq_bitmap)
 {
        struct nlattr *tb[ARRAY_SIZE(netdev_queue_id_nl_policy)];
+       struct nlattr *attr;
+       int rem, err = 0;
+       u32 rxq_idx;
+
+       nla_for_each_attr_type(attr, NETDEV_A_DMABUF_QUEUES,
+                              genlmsg_data(info->genlhdr),
+                              genlmsg_len(info->genlhdr), rem) {
+               err = nla_parse_nested(
+                       tb, ARRAY_SIZE(netdev_queue_id_nl_policy) - 1, attr,
+                       netdev_queue_id_nl_policy, info->extack);
+               if (err < 0)
+                       return err;
+
+               if (NL_REQ_ATTR_CHECK(info->extack, attr, tb, NETDEV_A_QUEUE_ID) ||
+                   NL_REQ_ATTR_CHECK(info->extack, attr, tb, NETDEV_A_QUEUE_TYPE))
+                       return -EINVAL;
+
+               if (nla_get_u32(tb[NETDEV_A_QUEUE_TYPE]) != NETDEV_QUEUE_TYPE_RX) {
+                       NL_SET_BAD_ATTR(info->extack, tb[NETDEV_A_QUEUE_TYPE]);
+                       return -EINVAL;
+               }
+
+               rxq_idx = nla_get_u32(tb[NETDEV_A_QUEUE_ID]);
+
+               bitmap_set(rxq_bitmap, rxq_idx, 1);
+       }
+
+       return 0;
+}
+
+int netdev_nl_bind_rx_doit(struct sk_buff *skb, struct genl_info *info)
+{
        struct net_devmem_dmabuf_binding *binding;
        u32 ifindex, dmabuf_fd, rxq_idx;
        struct netdev_nl_sock *priv;
        struct net_device *netdev;
+       unsigned long *rxq_bitmap;
        struct device *dma_dev;
        struct sk_buff *rsp;
-       struct nlattr *attr;
-       int rem, err = 0;
+       int err = 0;
        void *hdr;

        if (GENL_REQ_ATTR_CHECK(info, NETDEV_A_DEV_IFINDEX) ||
@@ -922,37 +955,22 @@ int netdev_nl_bind_rx_doit(struct sk_buff *skb, struct genl_info *info)
                goto err_unlock;
        }

+       rxq_bitmap = bitmap_alloc(netdev->num_rx_queues, GFP_KERNEL);
+       if (!rxq_bitmap) {
+               err = -ENOMEM;
+               goto err_unlock;
+       }
+       netdev_nl_read_rxq_bitmap(info, rxq_bitmap);
+
        dma_dev = netdev_queue_get_dma_dev(netdev, 0);
        binding = net_devmem_bind_dmabuf(netdev, dma_dev, DMA_FROM_DEVICE,
                                         dmabuf_fd, priv, info->extack);
        if (IS_ERR(binding)) {
                err = PTR_ERR(binding);
-               goto err_unlock;
+               goto err_rxq_bitmap;
        }

-       nla_for_each_attr_type(attr, NETDEV_A_DMABUF_QUEUES,
-                              genlmsg_data(info->genlhdr),
-                              genlmsg_len(info->genlhdr), rem) {
-               err = nla_parse_nested(
-                       tb, ARRAY_SIZE(netdev_queue_id_nl_policy) - 1, attr,
-                       netdev_queue_id_nl_policy, info->extack);
-               if (err < 0)
-                       goto err_unbind;
-
-               if (NL_REQ_ATTR_CHECK(info->extack, attr, tb, NETDEV_A_QUEUE_ID) ||
-                   NL_REQ_ATTR_CHECK(info->extack, attr, tb, NETDEV_A_QUEUE_TYPE)) {
-                       err = -EINVAL;
-                       goto err_unbind;
-               }
-
-               if (nla_get_u32(tb[NETDEV_A_QUEUE_TYPE]) != NETDEV_QUEUE_TYPE_RX) {
-                       NL_SET_BAD_ATTR(info->extack, tb[NETDEV_A_QUEUE_TYPE]);
-                       err = -EINVAL;
-                       goto err_unbind;
-               }
-
-               rxq_idx = nla_get_u32(tb[NETDEV_A_QUEUE_ID]);
-
+       for_each_set_bit(rxq_idx, rxq_bitmap, netdev->num_rx_queues) {
Is this code assuming that netdev->num_rx_queues (or
real_num_rx_queues) <= BITS_PER_ULONG? Aren't there devices out there
that support more than 64 hardware queues? If so, I guess you need a
different data structure than a bitmap (or maybe there is arbirary
sized bitmap library somewhere to use).
The bitmap API can handle any number of bits. Can it not?

Thanks,
Dragos
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help