On 2024-05-10 16:21, Mina Almasry wrote:
> -/* Stub */
>  int netdev_nl_bind_rx_doit(struct sk_buff *skb, struct genl_info *info)
>  {
> -     return 0;
> +     struct nlattr *tb[ARRAY_SIZE(netdev_queue_dmabuf_nl_policy)];
> +     struct net_devmem_dmabuf_binding *out_binding;
> +     struct list_head *sock_binding_list;
> +     u32 ifindex, dmabuf_fd, rxq_idx;
> +     struct net_device *netdev;
> +     struct sk_buff *rsp;
> +     struct nlattr *attr;
> +     int rem, err = 0;
> +     void *hdr;
> +
> +     if (GENL_REQ_ATTR_CHECK(info, NETDEV_A_DEV_IFINDEX) ||
> +         GENL_REQ_ATTR_CHECK(info, NETDEV_A_BIND_DMABUF_DMABUF_FD) ||
> +         GENL_REQ_ATTR_CHECK(info, NETDEV_A_BIND_DMABUF_QUEUES))
> +             return -EINVAL;
> +
> +     ifindex = nla_get_u32(info->attrs[NETDEV_A_DEV_IFINDEX]);
> +     dmabuf_fd = nla_get_u32(info->attrs[NETDEV_A_BIND_DMABUF_DMABUF_FD]);
> +
> +     rtnl_lock();
> +
> +     netdev = __dev_get_by_index(genl_info_net(info), ifindex);
> +     if (!netdev) {
> +             err = -ENODEV;
> +             goto err_unlock;
> +     }
> +
> +     err = net_devmem_bind_dmabuf(netdev, dmabuf_fd, &out_binding);
> +     if (err)
> +             goto err_unlock;
> +
> +     nla_for_each_attr(attr, genlmsg_data(info->genlhdr),
> +                       genlmsg_len(info->genlhdr), rem) {
> +             if (nla_type(attr) != NETDEV_A_BIND_DMABUF_QUEUES)
> +                     continue;
> +
> +             err = nla_parse_nested(
> +                     tb, ARRAY_SIZE(netdev_queue_dmabuf_nl_policy) - 1, attr,
> +                     netdev_queue_dmabuf_nl_policy, info->extack);
> +             if (err < 0)
> +                     goto err_unbind;
> +
> +             rxq_idx = nla_get_u32(tb[NETDEV_A_QUEUE_DMABUF_IDX]);
> +             if (rxq_idx >= netdev->num_rx_queues) {
> +                     err = -ERANGE;
> +                     goto err_unbind;
> +             }

net_devmem_bind_dmabuf_to_queue() checks for rxq_idx >=
netdev->num_rx_queues as well. I'd say remove the one in
netdev_nl_bind_rx_doit().

Also we may want a generic netdev function e.g. netdev_rx_queue_set_mp()
since I need the same functionality.

> +
> +             err = net_devmem_bind_dmabuf_to_queue(netdev, rxq_idx,
> +                                                   out_binding);
> +             if (err)
> +                     goto err_unbind;
> +     }
> +
> +     sock_binding_list = genl_sk_priv_get(&netdev_nl_family,
> +                                          NETLINK_CB(skb).sk);
> +     if (IS_ERR(sock_binding_list)) {
> +             err = PTR_ERR(sock_binding_list);
> +             goto err_unbind;
> +     }
> +
> +     list_add(&out_binding->list, sock_binding_list);
> +
> +     rsp = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL);
> +     if (!rsp) {
> +             err = -ENOMEM;
> +             goto err_unbind;
> +     }
> +
> +     hdr = genlmsg_iput(rsp, info);
> +     if (!hdr) {
> +             err = -EMSGSIZE;
> +             goto err_genlmsg_free;
> +     }
> +
> +     nla_put_u32(rsp, NETDEV_A_BIND_DMABUF_DMABUF_ID, out_binding->id);
> +     genlmsg_end(rsp, hdr);
> +
> +     rtnl_unlock();
> +
> +     return genlmsg_reply(rsp, info);
> +
> +err_genlmsg_free:
> +     nlmsg_free(rsp);
> +err_unbind:
> +     net_devmem_unbind_dmabuf(out_binding);
> +err_unlock:
> +     rtnl_unlock();
> +     return err;
>  }

Reply via email to