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

Dragos Tatulea posted 7 patches 1 month, 2 weeks ago
There is a newer version of this series
[RFC net-next v3 6/7] net: devmem: pre-read requested rx queues during bind
Posted by Dragos Tatulea 1 month, 2 weeks ago
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) {
 		err = net_devmem_bind_dmabuf_to_queue(netdev, rxq_idx, binding,
 						      info->extack);
 		if (err)
@@ -966,6 +984,8 @@ int netdev_nl_bind_rx_doit(struct sk_buff *skb, struct genl_info *info)
 	if (err)
 		goto err_unbind;
 
+	bitmap_free(rxq_bitmap);
+
 	netdev_unlock(netdev);
 
 	mutex_unlock(&priv->lock);
@@ -974,6 +994,8 @@ int netdev_nl_bind_rx_doit(struct sk_buff *skb, struct genl_info *info)
 
 err_unbind:
 	net_devmem_unbind_dmabuf(binding);
+err_rxq_bitmap:
+	bitmap_free(rxq_bitmap);
 err_unlock:
 	netdev_unlock(netdev);
 err_unlock_sock:
-- 
2.50.1
Re: [RFC net-next v3 6/7] net: devmem: pre-read requested rx queues during bind
Posted by ChaosEsque Team 1 day, 21 hours ago
Mina sounds like a girls name. Do you DOMINATE her?

On Fri, Aug 15, 2025 at 7:09 AM Dragos Tatulea <dtatulea@nvidia.com> wrote:
>
> 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) {
>                 err = net_devmem_bind_dmabuf_to_queue(netdev, rxq_idx, binding,
>                                                       info->extack);
>                 if (err)
> @@ -966,6 +984,8 @@ int netdev_nl_bind_rx_doit(struct sk_buff *skb, struct genl_info *info)
>         if (err)
>                 goto err_unbind;
>
> +       bitmap_free(rxq_bitmap);
> +
>         netdev_unlock(netdev);
>
>         mutex_unlock(&priv->lock);
> @@ -974,6 +994,8 @@ int netdev_nl_bind_rx_doit(struct sk_buff *skb, struct genl_info *info)
>
>  err_unbind:
>         net_devmem_unbind_dmabuf(binding);
> +err_rxq_bitmap:
> +       bitmap_free(rxq_bitmap);
>  err_unlock:
>         netdev_unlock(netdev);
>  err_unlock_sock:
> --
> 2.50.1
>
>
Re: [RFC net-next v3 6/7] net: devmem: pre-read requested rx queues during bind
Posted by Mina Almasry 1 month, 2 weeks ago
On Fri, Aug 15, 2025 at 4:07 AM Dragos Tatulea <dtatulea@nvidia.com> wrote:
>
> 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).



-- 
Thanks,
Mina
Re: [RFC net-next v3 6/7] net: devmem: pre-read requested rx queues during bind
Posted by Dragos Tatulea 1 month, 2 weeks ago
On Fri, Aug 15, 2025 at 11:05:56AM -0700, Mina Almasry wrote:
> On Fri, Aug 15, 2025 at 4:07 AM Dragos Tatulea <dtatulea@nvidia.com> wrote:
> >
> > 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
Re: [RFC net-next v3 6/7] net: devmem: pre-read requested rx queues during bind
Posted by Mina Almasry 1 month, 2 weeks ago
On Sat, Aug 16, 2025 at 1:59 AM Dragos Tatulea <dtatulea@nvidia.com> wrote:
>
> On Fri, Aug 15, 2025 at 11:05:56AM -0700, Mina Almasry wrote:
> > On Fri, Aug 15, 2025 at 4:07 AM Dragos Tatulea <dtatulea@nvidia.com> wrote:
> > >
> > > 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?
>

Ah, yes, I missed this:

+       rxq_bitmap = bitmap_alloc(netdev->num_rx_queues, GFP_KERNEL);


Which allocates netdev->num_rx_queues bits. I was confused by the fact
that rxq_bitmap is an unsigned long * and thought that was the # of
bits in the map.

This patch should be good just with conversion to netdev->real_num_rx_queues.

-- 
Thanks,
Mina
Re: [RFC net-next v3 6/7] net: devmem: pre-read requested rx queues during bind
Posted by Jakub Kicinski 1 month, 2 weeks ago
On Fri, 15 Aug 2025 14:03:47 +0300 Dragos Tatulea wrote:
> 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.

Nice!

> +	rxq_bitmap = bitmap_alloc(netdev->num_rx_queues, GFP_KERNEL);

FWIW I think you can use num_real_rx_queues since we're holding
the instance lock which prevents it from changing?

But it's just bits so doesn't matter all that much.