diff options
Diffstat (limited to 'drivers/infiniband/ulp/ipoib/ipoib_netlink.c')
| -rw-r--r-- | drivers/infiniband/ulp/ipoib/ipoib_netlink.c | 74 |
1 files changed, 52 insertions, 22 deletions
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_netlink.c b/drivers/infiniband/ulp/ipoib/ipoib_netlink.c index 74685936c948..53db7c8191e3 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_netlink.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_netlink.c @@ -31,7 +31,7 @@ */ #include <linux/netdevice.h> -#include <linux/module.h> +#include <linux/if_arp.h> /* For ARPHRD_xxx */ #include <net/rtnetlink.h> #include "ipoib.h" @@ -41,9 +41,14 @@ static const struct nla_policy ipoib_policy[IFLA_IPOIB_MAX + 1] = { [IFLA_IPOIB_UMCAST] = { .type = NLA_U16 }, }; +static unsigned int ipoib_get_max_num_queues(void) +{ + return min_t(unsigned int, num_possible_cpus(), 128); +} + static int ipoib_fill_info(struct sk_buff *skb, const struct net_device *dev) { - struct ipoib_dev_priv *priv = netdev_priv(dev); + struct ipoib_dev_priv *priv = ipoib_priv(dev); u16 val; if (nla_put_u16(skb, IFLA_IPOIB_PKEY, priv->pkey)) @@ -63,8 +68,9 @@ nla_put_failure: return -EMSGSIZE; } -static int ipoib_changelink(struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[]) +static int ipoib_changelink(struct net_device *dev, struct nlattr *tb[], + struct nlattr *data[], + struct netlink_ext_ack *extack) { u16 mode, umcast; int ret = 0; @@ -91,9 +97,13 @@ out_err: return ret; } -static int ipoib_new_child_link(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[]) +static int ipoib_new_child_link(struct net_device *dev, + struct rtnl_newlink_params *params, + struct netlink_ext_ack *extack) { + struct net *link_net = rtnl_newlink_link_net(params); + struct nlattr **data = params->data; + struct nlattr **tb = params->tb; struct net_device *pdev; struct ipoib_dev_priv *ppriv; u16 child_pkey; @@ -102,11 +112,11 @@ static int ipoib_new_child_link(struct net *src_net, struct net_device *dev, if (!tb[IFLA_LINK]) return -EINVAL; - pdev = __dev_get_by_index(src_net, nla_get_u32(tb[IFLA_LINK])); - if (!pdev) + pdev = __dev_get_by_index(link_net, nla_get_u32(tb[IFLA_LINK])); + if (!pdev || pdev->type != ARPHRD_INFINIBAND) return -ENODEV; - ppriv = netdev_priv(pdev); + ppriv = ipoib_priv(pdev); if (test_bit(IPOIB_FLAG_SUBINTERFACE, &ppriv->flags)) { ipoib_warn(ppriv, "child creation disallowed for child devices\n"); @@ -119,24 +129,36 @@ static int ipoib_new_child_link(struct net *src_net, struct net_device *dev, } else child_pkey = nla_get_u16(data[IFLA_IPOIB_PKEY]); - err = __ipoib_vlan_add(ppriv, netdev_priv(dev), child_pkey, IPOIB_RTNL_CHILD); + err = ipoib_intf_init(ppriv->ca, ppriv->port, dev->name, dev); + if (err) { + ipoib_warn(ppriv, "failed to initialize pkey device\n"); + return err; + } + + err = __ipoib_vlan_add(ppriv, ipoib_priv(dev), + child_pkey, IPOIB_RTNL_CHILD); + if (err) + return err; + + if (data) { + err = ipoib_changelink(dev, tb, data, extack); + if (err) { + unregister_netdevice(dev); + return err; + } + } - if (!err && data) - err = ipoib_changelink(dev, tb, data); - return err; + return 0; } -static void ipoib_unregister_child_dev(struct net_device *dev, struct list_head *head) +static void ipoib_del_child_link(struct net_device *dev, struct list_head *head) { - struct ipoib_dev_priv *priv, *ppriv; + struct ipoib_dev_priv *priv = ipoib_priv(dev); - priv = netdev_priv(dev); - ppriv = netdev_priv(priv->parent); + if (!priv->parent) + return; - mutex_lock(&ppriv->vlan_mutex); unregister_netdevice_queue(dev, head); - list_del(&priv->list); - mutex_unlock(&ppriv->vlan_mutex); } static size_t ipoib_get_size(const struct net_device *dev) @@ -148,17 +170,25 @@ static size_t ipoib_get_size(const struct net_device *dev) static struct rtnl_link_ops ipoib_link_ops __read_mostly = { .kind = "ipoib", + .netns_refund = true, .maxtype = IFLA_IPOIB_MAX, .policy = ipoib_policy, .priv_size = sizeof(struct ipoib_dev_priv), - .setup = ipoib_setup, + .setup = ipoib_setup_common, .newlink = ipoib_new_child_link, + .dellink = ipoib_del_child_link, .changelink = ipoib_changelink, - .dellink = ipoib_unregister_child_dev, .get_size = ipoib_get_size, .fill_info = ipoib_fill_info, + .get_num_rx_queues = ipoib_get_max_num_queues, + .get_num_tx_queues = ipoib_get_max_num_queues, }; +struct rtnl_link_ops *ipoib_get_link_ops(void) +{ + return &ipoib_link_ops; +} + int __init ipoib_netlink_init(void) { return rtnl_link_register(&ipoib_link_ops); |
