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>
此提交包含在:
@@ -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);
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
/* MTU will be reset when mcast join happens */
|
||||
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))
|
||||
goto sysfs_failed;
|
||||
|
||||
priv->child_type = type;
|
||||
list_add_tail(&priv->list, &ppriv->child_intfs);
|
||||
|
||||
mutex_unlock(&ppriv->vlan_mutex);
|
||||
rtnl_unlock();
|
||||
|
||||
return 0;
|
||||
|
||||
sysfs_failed:
|
||||
result = -ENOMEM;
|
||||
ipoib_delete_debug_files(priv->dev);
|
||||
unregister_netdevice(priv->dev);
|
||||
|
||||
@@ -149,11 +112,60 @@ register_failed:
|
||||
ipoib_dev_cleanup(priv->dev);
|
||||
|
||||
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);
|
||||
rtnl_unlock();
|
||||
if (priv)
|
||||
|
||||
if (result)
|
||||
free_netdev(priv->dev);
|
||||
|
||||
rtnl_unlock();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -171,9 +183,9 @@ int ipoib_vlan_delete(struct net_device *pdev, unsigned short pkey)
|
||||
return restart_syscall();
|
||||
mutex_lock(&ppriv->vlan_mutex);
|
||||
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);
|
||||
ipoib_dev_cleanup(priv->dev);
|
||||
list_del(&priv->list);
|
||||
dev = priv->dev;
|
||||
break;
|
||||
|
新增問題並參考
封鎖使用者