IB/ipoib: Add rtnl_link_ops support
Add rtnl_link_ops to IPoIB, with the first usage being child device create/delete through them. Childs devices are now either legacy ones, created/deleted through the ipoib sysfs entries, or RTNL ones. Adding support for RTNL childs involved refactoring of ipoib_vlan_add which is now used by both the sysfs and the link_ops code. Also, added ndo_uninit entry to support calling unregister_netdevice_queue from the rtnl dellink entry. This required removal of calls to ipoib_dev_cleanup from the driver in flows which use unregister_netdevice, since the networking core will invoke ipoib_uninit which does exactly that. Signed-off-by: Erez Shitrit <erezsh@mellanox.co.il> Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Родитель
b85c715c2e
Коммит
9baa0b0364
|
@ -24,6 +24,9 @@ Partitions and P_Keys
|
||||||
The P_Key for any interface is given by the "pkey" file, and the
|
The P_Key for any interface is given by the "pkey" file, and the
|
||||||
main interface for a subinterface is in "parent."
|
main interface for a subinterface is in "parent."
|
||||||
|
|
||||||
|
Child interface create/delete can also be done using IPoIB's
|
||||||
|
rtnl_link_ops, where childs created using either way behave the same.
|
||||||
|
|
||||||
Datagram vs Connected modes
|
Datagram vs Connected modes
|
||||||
|
|
||||||
The IPoIB driver supports two modes of operation: datagram and
|
The IPoIB driver supports two modes of operation: datagram and
|
||||||
|
|
|
@ -5,7 +5,8 @@ ib_ipoib-y := ipoib_main.o \
|
||||||
ipoib_multicast.o \
|
ipoib_multicast.o \
|
||||||
ipoib_verbs.o \
|
ipoib_verbs.o \
|
||||||
ipoib_vlan.o \
|
ipoib_vlan.o \
|
||||||
ipoib_ethtool.o
|
ipoib_ethtool.o \
|
||||||
|
ipoib_netlink.o
|
||||||
ib_ipoib-$(CONFIG_INFINIBAND_IPOIB_CM) += ipoib_cm.o
|
ib_ipoib-$(CONFIG_INFINIBAND_IPOIB_CM) += ipoib_cm.o
|
||||||
ib_ipoib-$(CONFIG_INFINIBAND_IPOIB_DEBUG) += ipoib_fs.o
|
ib_ipoib-$(CONFIG_INFINIBAND_IPOIB_DEBUG) += ipoib_fs.o
|
||||||
|
|
||||||
|
|
|
@ -104,6 +104,10 @@ enum {
|
||||||
|
|
||||||
MAX_SEND_CQE = 16,
|
MAX_SEND_CQE = 16,
|
||||||
IPOIB_CM_COPYBREAK = 256,
|
IPOIB_CM_COPYBREAK = 256,
|
||||||
|
|
||||||
|
IPOIB_NON_CHILD = 0,
|
||||||
|
IPOIB_LEGACY_CHILD = 1,
|
||||||
|
IPOIB_RTNL_CHILD = 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define IPOIB_OP_RECV (1ul << 31)
|
#define IPOIB_OP_RECV (1ul << 31)
|
||||||
|
@ -350,6 +354,7 @@ struct ipoib_dev_priv {
|
||||||
struct net_device *parent;
|
struct net_device *parent;
|
||||||
struct list_head child_intfs;
|
struct list_head child_intfs;
|
||||||
struct list_head list;
|
struct list_head list;
|
||||||
|
int child_type;
|
||||||
|
|
||||||
#ifdef CONFIG_INFINIBAND_IPOIB_CM
|
#ifdef CONFIG_INFINIBAND_IPOIB_CM
|
||||||
struct ipoib_cm_dev_priv cm;
|
struct ipoib_cm_dev_priv cm;
|
||||||
|
@ -509,6 +514,14 @@ void ipoib_event(struct ib_event_handler *handler,
|
||||||
int ipoib_vlan_add(struct net_device *pdev, unsigned short pkey);
|
int ipoib_vlan_add(struct net_device *pdev, unsigned short pkey);
|
||||||
int ipoib_vlan_delete(struct net_device *pdev, unsigned short pkey);
|
int ipoib_vlan_delete(struct net_device *pdev, unsigned short pkey);
|
||||||
|
|
||||||
|
int __ipoib_vlan_add(struct ipoib_dev_priv *ppriv, struct ipoib_dev_priv *priv,
|
||||||
|
u16 pkey, int child_type);
|
||||||
|
|
||||||
|
int __init ipoib_netlink_init(void);
|
||||||
|
void __exit ipoib_netlink_fini(void);
|
||||||
|
|
||||||
|
void ipoib_setup(struct net_device *dev);
|
||||||
|
|
||||||
void ipoib_pkey_poll(struct work_struct *work);
|
void ipoib_pkey_poll(struct work_struct *work);
|
||||||
int ipoib_pkey_dev_delay_open(struct net_device *dev);
|
int ipoib_pkey_dev_delay_open(struct net_device *dev);
|
||||||
void ipoib_drain_cq(struct net_device *dev);
|
void ipoib_drain_cq(struct net_device *dev);
|
||||||
|
|
|
@ -173,6 +173,11 @@ static int ipoib_stop(struct net_device *dev)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ipoib_uninit(struct net_device *dev)
|
||||||
|
{
|
||||||
|
ipoib_dev_cleanup(dev);
|
||||||
|
}
|
||||||
|
|
||||||
static netdev_features_t ipoib_fix_features(struct net_device *dev, netdev_features_t features)
|
static netdev_features_t ipoib_fix_features(struct net_device *dev, netdev_features_t features)
|
||||||
{
|
{
|
||||||
struct ipoib_dev_priv *priv = netdev_priv(dev);
|
struct ipoib_dev_priv *priv = netdev_priv(dev);
|
||||||
|
@ -1262,6 +1267,9 @@ out:
|
||||||
void ipoib_dev_cleanup(struct net_device *dev)
|
void ipoib_dev_cleanup(struct net_device *dev)
|
||||||
{
|
{
|
||||||
struct ipoib_dev_priv *priv = netdev_priv(dev), *cpriv, *tcpriv;
|
struct ipoib_dev_priv *priv = netdev_priv(dev), *cpriv, *tcpriv;
|
||||||
|
LIST_HEAD(head);
|
||||||
|
|
||||||
|
ASSERT_RTNL();
|
||||||
|
|
||||||
ipoib_delete_debug_files(dev);
|
ipoib_delete_debug_files(dev);
|
||||||
|
|
||||||
|
@ -1270,10 +1278,9 @@ void ipoib_dev_cleanup(struct net_device *dev)
|
||||||
/* Stop GC on child */
|
/* Stop GC on child */
|
||||||
set_bit(IPOIB_STOP_NEIGH_GC, &cpriv->flags);
|
set_bit(IPOIB_STOP_NEIGH_GC, &cpriv->flags);
|
||||||
cancel_delayed_work(&cpriv->neigh_reap_task);
|
cancel_delayed_work(&cpriv->neigh_reap_task);
|
||||||
unregister_netdev(cpriv->dev);
|
unregister_netdevice_queue(cpriv->dev, &head);
|
||||||
ipoib_dev_cleanup(cpriv->dev);
|
|
||||||
free_netdev(cpriv->dev);
|
|
||||||
}
|
}
|
||||||
|
unregister_netdevice_many(&head);
|
||||||
|
|
||||||
ipoib_ib_dev_cleanup(dev);
|
ipoib_ib_dev_cleanup(dev);
|
||||||
|
|
||||||
|
@ -1291,6 +1298,7 @@ static const struct header_ops ipoib_header_ops = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct net_device_ops ipoib_netdev_ops = {
|
static const struct net_device_ops ipoib_netdev_ops = {
|
||||||
|
.ndo_uninit = ipoib_uninit,
|
||||||
.ndo_open = ipoib_open,
|
.ndo_open = ipoib_open,
|
||||||
.ndo_stop = ipoib_stop,
|
.ndo_stop = ipoib_stop,
|
||||||
.ndo_change_mtu = ipoib_change_mtu,
|
.ndo_change_mtu = ipoib_change_mtu,
|
||||||
|
@ -1300,7 +1308,7 @@ static const struct net_device_ops ipoib_netdev_ops = {
|
||||||
.ndo_set_rx_mode = ipoib_set_mcast_list,
|
.ndo_set_rx_mode = ipoib_set_mcast_list,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void ipoib_setup(struct net_device *dev)
|
void ipoib_setup(struct net_device *dev)
|
||||||
{
|
{
|
||||||
struct ipoib_dev_priv *priv = netdev_priv(dev);
|
struct ipoib_dev_priv *priv = netdev_priv(dev);
|
||||||
|
|
||||||
|
@ -1662,7 +1670,6 @@ static void ipoib_remove_one(struct ib_device *device)
|
||||||
flush_workqueue(ipoib_workqueue);
|
flush_workqueue(ipoib_workqueue);
|
||||||
|
|
||||||
unregister_netdev(priv->dev);
|
unregister_netdev(priv->dev);
|
||||||
ipoib_dev_cleanup(priv->dev);
|
|
||||||
free_netdev(priv->dev);
|
free_netdev(priv->dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1714,8 +1721,15 @@ static int __init ipoib_init_module(void)
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err_sa;
|
goto err_sa;
|
||||||
|
|
||||||
|
ret = ipoib_netlink_init();
|
||||||
|
if (ret)
|
||||||
|
goto err_client;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
err_client:
|
||||||
|
ib_unregister_client(&ipoib_client);
|
||||||
|
|
||||||
err_sa:
|
err_sa:
|
||||||
ib_sa_unregister_client(&ipoib_sa_client);
|
ib_sa_unregister_client(&ipoib_sa_client);
|
||||||
destroy_workqueue(ipoib_workqueue);
|
destroy_workqueue(ipoib_workqueue);
|
||||||
|
@ -1728,6 +1742,7 @@ err_fs:
|
||||||
|
|
||||||
static void __exit ipoib_cleanup_module(void)
|
static void __exit ipoib_cleanup_module(void)
|
||||||
{
|
{
|
||||||
|
ipoib_netlink_fini();
|
||||||
ib_unregister_client(&ipoib_client);
|
ib_unregister_client(&ipoib_client);
|
||||||
ib_sa_unregister_client(&ipoib_sa_client);
|
ib_sa_unregister_client(&ipoib_sa_client);
|
||||||
ipoib_unregister_debugfs();
|
ipoib_unregister_debugfs();
|
||||||
|
|
|
@ -0,0 +1,114 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2012 Mellanox Technologies. - All rights reserved.
|
||||||
|
*
|
||||||
|
* This software is available to you under a choice of one of two
|
||||||
|
* licenses. You may choose to be licensed under the terms of the GNU
|
||||||
|
* General Public License (GPL) Version 2, available from the file
|
||||||
|
* COPYING in the main directory of this source tree, or the
|
||||||
|
* OpenIB.org BSD license below:
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or
|
||||||
|
* without modification, are permitted provided that the following
|
||||||
|
* conditions are met:
|
||||||
|
*
|
||||||
|
* - Redistributions of source code must retain the above
|
||||||
|
* copyright notice, this list of conditions and the following
|
||||||
|
* disclaimer.
|
||||||
|
*
|
||||||
|
* - Redistributions in binary form must reproduce the above
|
||||||
|
* copyright notice, this list of conditions and the following
|
||||||
|
* disclaimer in the documentation and/or other materials
|
||||||
|
* provided with the distribution.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/netdevice.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <net/rtnetlink.h>
|
||||||
|
#include "ipoib.h"
|
||||||
|
|
||||||
|
static const struct nla_policy ipoib_policy[IFLA_IPOIB_MAX + 1] = {
|
||||||
|
[IFLA_IPOIB_PKEY] = { .type = NLA_U16 },
|
||||||
|
};
|
||||||
|
|
||||||
|
static int ipoib_new_child_link(struct net *src_net, struct net_device *dev,
|
||||||
|
struct nlattr *tb[], struct nlattr *data[])
|
||||||
|
{
|
||||||
|
struct net_device *pdev;
|
||||||
|
struct ipoib_dev_priv *ppriv;
|
||||||
|
u16 child_pkey;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
if (!tb[IFLA_LINK])
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
pdev = __dev_get_by_index(src_net, nla_get_u32(tb[IFLA_LINK]));
|
||||||
|
if (!pdev)
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
ppriv = netdev_priv(pdev);
|
||||||
|
|
||||||
|
if (test_bit(IPOIB_FLAG_SUBINTERFACE, &ppriv->flags)) {
|
||||||
|
ipoib_warn(ppriv, "child creation disallowed for child devices\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!data || !data[IFLA_IPOIB_PKEY]) {
|
||||||
|
ipoib_dbg(ppriv, "no pkey specified, using parent pkey\n");
|
||||||
|
child_pkey = ppriv->pkey;
|
||||||
|
} else
|
||||||
|
child_pkey = nla_get_u16(data[IFLA_IPOIB_PKEY]);
|
||||||
|
|
||||||
|
err = __ipoib_vlan_add(ppriv, netdev_priv(dev), child_pkey, IPOIB_RTNL_CHILD);
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ipoib_unregister_child_dev(struct net_device *dev, struct list_head *head)
|
||||||
|
{
|
||||||
|
struct ipoib_dev_priv *priv, *ppriv;
|
||||||
|
|
||||||
|
priv = netdev_priv(dev);
|
||||||
|
ppriv = netdev_priv(priv->parent);
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
return nla_total_size(2); /* IFLA_IPOIB_PKEY */
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct rtnl_link_ops ipoib_link_ops __read_mostly = {
|
||||||
|
.kind = "ipoib",
|
||||||
|
.maxtype = IFLA_IPOIB_MAX,
|
||||||
|
.policy = ipoib_policy,
|
||||||
|
.priv_size = sizeof(struct ipoib_dev_priv),
|
||||||
|
.setup = ipoib_setup,
|
||||||
|
.newlink = ipoib_new_child_link,
|
||||||
|
.dellink = ipoib_unregister_child_dev,
|
||||||
|
.get_size = ipoib_get_size,
|
||||||
|
};
|
||||||
|
|
||||||
|
int __init ipoib_netlink_init(void)
|
||||||
|
{
|
||||||
|
return rtnl_link_register(&ipoib_link_ops);
|
||||||
|
}
|
||||||
|
|
||||||
|
void __exit ipoib_netlink_fini(void)
|
||||||
|
{
|
||||||
|
rtnl_link_unregister(&ipoib_link_ops);
|
||||||
|
}
|
||||||
|
|
||||||
|
MODULE_ALIAS_RTNL_LINK("ipoib");
|
|
@ -49,47 +49,11 @@ static ssize_t show_parent(struct device *d, struct device_attribute *attr,
|
||||||
}
|
}
|
||||||
static DEVICE_ATTR(parent, S_IRUGO, show_parent, NULL);
|
static DEVICE_ATTR(parent, S_IRUGO, show_parent, NULL);
|
||||||
|
|
||||||
int ipoib_vlan_add(struct net_device *pdev, unsigned short pkey)
|
int __ipoib_vlan_add(struct ipoib_dev_priv *ppriv, struct ipoib_dev_priv *priv,
|
||||||
|
u16 pkey, int type)
|
||||||
{
|
{
|
||||||
struct ipoib_dev_priv *ppriv, *priv;
|
|
||||||
char intf_name[IFNAMSIZ];
|
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
if (!capable(CAP_NET_ADMIN))
|
|
||||||
return -EPERM;
|
|
||||||
|
|
||||||
ppriv = netdev_priv(pdev);
|
|
||||||
|
|
||||||
if (!rtnl_trylock())
|
|
||||||
return restart_syscall();
|
|
||||||
mutex_lock(&ppriv->vlan_mutex);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* First ensure this isn't a duplicate. We check the parent device and
|
|
||||||
* then all of the child interfaces to make sure the Pkey doesn't match.
|
|
||||||
*/
|
|
||||||
if (ppriv->pkey == pkey) {
|
|
||||||
result = -ENOTUNIQ;
|
|
||||||
priv = NULL;
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
list_for_each_entry(priv, &ppriv->child_intfs, list) {
|
|
||||||
if (priv->pkey == pkey) {
|
|
||||||
result = -ENOTUNIQ;
|
|
||||||
priv = NULL;
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
snprintf(intf_name, sizeof intf_name, "%s.%04x",
|
|
||||||
ppriv->dev->name, pkey);
|
|
||||||
priv = ipoib_intf_alloc(intf_name);
|
|
||||||
if (!priv) {
|
|
||||||
result = -ENOMEM;
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
priv->max_ib_mtu = ppriv->max_ib_mtu;
|
priv->max_ib_mtu = ppriv->max_ib_mtu;
|
||||||
/* MTU will be reset when mcast join happens */
|
/* MTU will be reset when mcast join happens */
|
||||||
priv->dev->mtu = IPOIB_UD_MTU(priv->max_ib_mtu);
|
priv->dev->mtu = IPOIB_UD_MTU(priv->max_ib_mtu);
|
||||||
|
@ -134,14 +98,13 @@ int ipoib_vlan_add(struct net_device *pdev, unsigned short pkey)
|
||||||
if (device_create_file(&priv->dev->dev, &dev_attr_parent))
|
if (device_create_file(&priv->dev->dev, &dev_attr_parent))
|
||||||
goto sysfs_failed;
|
goto sysfs_failed;
|
||||||
|
|
||||||
|
priv->child_type = type;
|
||||||
list_add_tail(&priv->list, &ppriv->child_intfs);
|
list_add_tail(&priv->list, &ppriv->child_intfs);
|
||||||
|
|
||||||
mutex_unlock(&ppriv->vlan_mutex);
|
|
||||||
rtnl_unlock();
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
sysfs_failed:
|
sysfs_failed:
|
||||||
|
result = -ENOMEM;
|
||||||
ipoib_delete_debug_files(priv->dev);
|
ipoib_delete_debug_files(priv->dev);
|
||||||
unregister_netdevice(priv->dev);
|
unregister_netdevice(priv->dev);
|
||||||
|
|
||||||
|
@ -149,11 +112,60 @@ register_failed:
|
||||||
ipoib_dev_cleanup(priv->dev);
|
ipoib_dev_cleanup(priv->dev);
|
||||||
|
|
||||||
err:
|
err:
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ipoib_vlan_add(struct net_device *pdev, unsigned short pkey)
|
||||||
|
{
|
||||||
|
struct ipoib_dev_priv *ppriv, *priv;
|
||||||
|
char intf_name[IFNAMSIZ];
|
||||||
|
struct ipoib_dev_priv *tpriv;
|
||||||
|
int result;
|
||||||
|
|
||||||
|
if (!capable(CAP_NET_ADMIN))
|
||||||
|
return -EPERM;
|
||||||
|
|
||||||
|
ppriv = netdev_priv(pdev);
|
||||||
|
|
||||||
|
snprintf(intf_name, sizeof intf_name, "%s.%04x",
|
||||||
|
ppriv->dev->name, pkey);
|
||||||
|
priv = ipoib_intf_alloc(intf_name);
|
||||||
|
if (!priv)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
if (!rtnl_trylock())
|
||||||
|
return restart_syscall();
|
||||||
|
|
||||||
|
mutex_lock(&ppriv->vlan_mutex);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* First ensure this isn't a duplicate. We check the parent device and
|
||||||
|
* then all of the legacy child interfaces to make sure the Pkey
|
||||||
|
* doesn't match.
|
||||||
|
*/
|
||||||
|
if (ppriv->pkey == pkey) {
|
||||||
|
result = -ENOTUNIQ;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
list_for_each_entry(tpriv, &ppriv->child_intfs, list) {
|
||||||
|
if (tpriv->pkey == pkey &&
|
||||||
|
tpriv->child_type == IPOIB_LEGACY_CHILD) {
|
||||||
|
result = -ENOTUNIQ;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result = __ipoib_vlan_add(ppriv, priv, pkey, IPOIB_LEGACY_CHILD);
|
||||||
|
|
||||||
|
out:
|
||||||
mutex_unlock(&ppriv->vlan_mutex);
|
mutex_unlock(&ppriv->vlan_mutex);
|
||||||
rtnl_unlock();
|
|
||||||
if (priv)
|
if (result)
|
||||||
free_netdev(priv->dev);
|
free_netdev(priv->dev);
|
||||||
|
|
||||||
|
rtnl_unlock();
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,9 +183,9 @@ int ipoib_vlan_delete(struct net_device *pdev, unsigned short pkey)
|
||||||
return restart_syscall();
|
return restart_syscall();
|
||||||
mutex_lock(&ppriv->vlan_mutex);
|
mutex_lock(&ppriv->vlan_mutex);
|
||||||
list_for_each_entry_safe(priv, tpriv, &ppriv->child_intfs, list) {
|
list_for_each_entry_safe(priv, tpriv, &ppriv->child_intfs, list) {
|
||||||
if (priv->pkey == pkey) {
|
if (priv->pkey == pkey &&
|
||||||
|
priv->child_type == IPOIB_LEGACY_CHILD) {
|
||||||
unregister_netdevice(priv->dev);
|
unregister_netdevice(priv->dev);
|
||||||
ipoib_dev_cleanup(priv->dev);
|
|
||||||
list_del(&priv->list);
|
list_del(&priv->list);
|
||||||
dev = priv->dev;
|
dev = priv->dev;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -398,4 +398,15 @@ struct ifla_port_vsi {
|
||||||
__u8 pad[3];
|
__u8 pad[3];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* IPoIB section */
|
||||||
|
|
||||||
|
enum {
|
||||||
|
IFLA_IPOIB_UNSPEC,
|
||||||
|
IFLA_IPOIB_PKEY,
|
||||||
|
__IFLA_IPOIB_MAX
|
||||||
|
};
|
||||||
|
|
||||||
|
#define IFLA_IPOIB_MAX (__IFLA_IPOIB_MAX - 1)
|
||||||
|
|
||||||
#endif /* _LINUX_IF_LINK_H */
|
#endif /* _LINUX_IF_LINK_H */
|
||||||
|
|
Загрузка…
Ссылка в новой задаче