ipoib_vlan.c (7531B)
1/* 2 * Copyright (c) 2004 Topspin Communications. All rights reserved. 3 * 4 * This software is available to you under a choice of one of two 5 * licenses. You may choose to be licensed under the terms of the GNU 6 * General Public License (GPL) Version 2, available from the file 7 * COPYING in the main directory of this source tree, or the 8 * OpenIB.org BSD license below: 9 * 10 * Redistribution and use in source and binary forms, with or 11 * without modification, are permitted provided that the following 12 * conditions are met: 13 * 14 * - Redistributions of source code must retain the above 15 * copyright notice, this list of conditions and the following 16 * disclaimer. 17 * 18 * - Redistributions in binary form must reproduce the above 19 * copyright notice, this list of conditions and the following 20 * disclaimer in the documentation and/or other materials 21 * provided with the distribution. 22 * 23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 27 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 28 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 29 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30 * SOFTWARE. 31 */ 32 33#include <linux/sched/signal.h> 34 35#include <linux/init.h> 36#include <linux/seq_file.h> 37 38#include <linux/uaccess.h> 39 40#include "ipoib.h" 41 42static ssize_t parent_show(struct device *d, struct device_attribute *attr, 43 char *buf) 44{ 45 struct net_device *dev = to_net_dev(d); 46 struct ipoib_dev_priv *priv = ipoib_priv(dev); 47 48 return sysfs_emit(buf, "%s\n", priv->parent->name); 49} 50static DEVICE_ATTR_RO(parent); 51 52static bool is_child_unique(struct ipoib_dev_priv *ppriv, 53 struct ipoib_dev_priv *priv) 54{ 55 struct ipoib_dev_priv *tpriv; 56 57 ASSERT_RTNL(); 58 59 /* 60 * Since the legacy sysfs interface uses pkey for deletion it cannot 61 * support more than one interface with the same pkey, it creates 62 * ambiguity. The RTNL interface deletes using the netdev so it does 63 * not have a problem to support duplicated pkeys. 64 */ 65 if (priv->child_type != IPOIB_LEGACY_CHILD) 66 return true; 67 68 /* 69 * First ensure this isn't a duplicate. We check the parent device and 70 * then all of the legacy child interfaces to make sure the Pkey 71 * doesn't match. 72 */ 73 if (ppriv->pkey == priv->pkey) 74 return false; 75 76 list_for_each_entry(tpriv, &ppriv->child_intfs, list) { 77 if (tpriv->pkey == priv->pkey && 78 tpriv->child_type == IPOIB_LEGACY_CHILD) 79 return false; 80 } 81 82 return true; 83} 84 85/* 86 * NOTE: If this function fails then the priv->dev will remain valid, however 87 * priv will have been freed and must not be touched by caller in the error 88 * case. 89 * 90 * If (ndev->reg_state == NETREG_UNINITIALIZED) then it is up to the caller to 91 * free the net_device (just as rtnl_newlink does) otherwise the net_device 92 * will be freed when the rtnl is unlocked. 93 */ 94int __ipoib_vlan_add(struct ipoib_dev_priv *ppriv, struct ipoib_dev_priv *priv, 95 u16 pkey, int type) 96{ 97 struct net_device *ndev = priv->dev; 98 int result; 99 struct rdma_netdev *rn = netdev_priv(ndev); 100 101 ASSERT_RTNL(); 102 103 /* 104 * We do not need to touch priv if register_netdevice fails, so just 105 * always use this flow. 106 */ 107 ndev->priv_destructor = ipoib_intf_free; 108 109 /* 110 * Racing with unregister of the parent must be prevented by the 111 * caller. 112 */ 113 WARN_ON(ppriv->dev->reg_state != NETREG_REGISTERED); 114 115 if (pkey == 0 || pkey == 0x8000) { 116 result = -EINVAL; 117 goto out_early; 118 } 119 120 rn->mtu = priv->mcast_mtu; 121 122 priv->parent = ppriv->dev; 123 priv->pkey = pkey; 124 priv->child_type = type; 125 126 if (!is_child_unique(ppriv, priv)) { 127 result = -ENOTUNIQ; 128 goto out_early; 129 } 130 131 result = register_netdevice(ndev); 132 if (result) { 133 ipoib_warn(priv, "failed to initialize; error %i", result); 134 135 /* 136 * register_netdevice sometimes calls priv_destructor, 137 * sometimes not. Make sure it was done. 138 */ 139 goto out_early; 140 } 141 142 /* RTNL childs don't need proprietary sysfs entries */ 143 if (type == IPOIB_LEGACY_CHILD) { 144 if (ipoib_cm_add_mode_attr(ndev)) 145 goto sysfs_failed; 146 if (ipoib_add_pkey_attr(ndev)) 147 goto sysfs_failed; 148 if (ipoib_add_umcast_attr(ndev)) 149 goto sysfs_failed; 150 151 if (device_create_file(&ndev->dev, &dev_attr_parent)) 152 goto sysfs_failed; 153 } 154 155 return 0; 156 157sysfs_failed: 158 unregister_netdevice(priv->dev); 159 return -ENOMEM; 160 161out_early: 162 if (ndev->priv_destructor) 163 ndev->priv_destructor(ndev); 164 return result; 165} 166 167int ipoib_vlan_add(struct net_device *pdev, unsigned short pkey) 168{ 169 struct ipoib_dev_priv *ppriv, *priv; 170 char intf_name[IFNAMSIZ]; 171 struct net_device *ndev; 172 int result; 173 174 if (!capable(CAP_NET_ADMIN)) 175 return -EPERM; 176 177 if (!rtnl_trylock()) 178 return restart_syscall(); 179 180 if (pdev->reg_state != NETREG_REGISTERED) { 181 rtnl_unlock(); 182 return -EPERM; 183 } 184 185 ppriv = ipoib_priv(pdev); 186 187 snprintf(intf_name, sizeof(intf_name), "%s.%04x", 188 ppriv->dev->name, pkey); 189 190 ndev = ipoib_intf_alloc(ppriv->ca, ppriv->port, intf_name); 191 if (IS_ERR(ndev)) { 192 result = PTR_ERR(ndev); 193 goto out; 194 } 195 priv = ipoib_priv(ndev); 196 197 ndev->rtnl_link_ops = ipoib_get_link_ops(); 198 199 result = __ipoib_vlan_add(ppriv, priv, pkey, IPOIB_LEGACY_CHILD); 200 201 if (result && ndev->reg_state == NETREG_UNINITIALIZED) 202 free_netdev(ndev); 203 204out: 205 rtnl_unlock(); 206 207 return result; 208} 209 210struct ipoib_vlan_delete_work { 211 struct work_struct work; 212 struct net_device *dev; 213}; 214 215/* 216 * sysfs callbacks of a netdevice cannot obtain the rtnl lock as 217 * unregister_netdev ultimately deletes the sysfs files while holding the rtnl 218 * lock. This deadlocks the system. 219 * 220 * A callback can use rtnl_trylock to avoid the deadlock but it cannot call 221 * unregister_netdev as that internally takes and releases the rtnl_lock. So 222 * instead we find the netdev to unregister and then do the actual unregister 223 * from the global work queue where we can obtain the rtnl_lock safely. 224 */ 225static void ipoib_vlan_delete_task(struct work_struct *work) 226{ 227 struct ipoib_vlan_delete_work *pwork = 228 container_of(work, struct ipoib_vlan_delete_work, work); 229 struct net_device *dev = pwork->dev; 230 231 rtnl_lock(); 232 233 /* Unregistering tasks can race with another task or parent removal */ 234 if (dev->reg_state == NETREG_REGISTERED) { 235 struct ipoib_dev_priv *priv = ipoib_priv(dev); 236 struct ipoib_dev_priv *ppriv = ipoib_priv(priv->parent); 237 238 ipoib_dbg(ppriv, "delete child vlan %s\n", dev->name); 239 unregister_netdevice(dev); 240 } 241 242 rtnl_unlock(); 243 244 kfree(pwork); 245} 246 247int ipoib_vlan_delete(struct net_device *pdev, unsigned short pkey) 248{ 249 struct ipoib_dev_priv *ppriv, *priv, *tpriv; 250 int rc; 251 252 if (!capable(CAP_NET_ADMIN)) 253 return -EPERM; 254 255 if (!rtnl_trylock()) 256 return restart_syscall(); 257 258 if (pdev->reg_state != NETREG_REGISTERED) { 259 rtnl_unlock(); 260 return -EPERM; 261 } 262 263 ppriv = ipoib_priv(pdev); 264 265 rc = -ENODEV; 266 list_for_each_entry_safe(priv, tpriv, &ppriv->child_intfs, list) { 267 if (priv->pkey == pkey && 268 priv->child_type == IPOIB_LEGACY_CHILD) { 269 struct ipoib_vlan_delete_work *work; 270 271 work = kmalloc(sizeof(*work), GFP_KERNEL); 272 if (!work) { 273 rc = -ENOMEM; 274 goto out; 275 } 276 277 down_write(&ppriv->vlan_rwsem); 278 list_del_init(&priv->list); 279 up_write(&ppriv->vlan_rwsem); 280 work->dev = priv->dev; 281 INIT_WORK(&work->work, ipoib_vlan_delete_task); 282 queue_work(ipoib_workqueue, &work->work); 283 284 rc = 0; 285 break; 286 } 287 } 288 289out: 290 rtnl_unlock(); 291 292 return rc; 293}