298 lines · c
1/*2 * Copyright (c) 2004 Topspin Communications. All rights reserved.3 *4 * This software is available to you under a choice of one of two5 * licenses. You may choose to be licensed under the terms of the GNU6 * General Public License (GPL) Version 2, available from the file7 * COPYING in the main directory of this source tree, or the8 * OpenIB.org BSD license below:9 *10 * Redistribution and use in source and binary forms, with or11 * without modification, are permitted provided that the following12 * conditions are met:13 *14 * - Redistributions of source code must retain the above15 * copyright notice, this list of conditions and the following16 * disclaimer.17 *18 * - Redistributions in binary form must reproduce the above19 * copyright notice, this list of conditions and the following20 * disclaimer in the documentation and/or other materials21 * 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 OF25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND26 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS27 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN28 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN29 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE30 * 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 cannot61 * support more than one interface with the same pkey, it creates62 * ambiguity. The RTNL interface deletes using the netdev so it does63 * 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 and70 * then all of the legacy child interfaces to make sure the Pkey71 * 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, however87 * priv will have been freed and must not be touched by caller in the error88 * case.89 *90 * If (ndev->reg_state == NETREG_UNINITIALIZED) then it is up to the caller to91 * free the net_device (just as rtnl_newlink does) otherwise the net_device92 * 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 just105 * 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 the111 * 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 /* If you increase IFNAMSIZ, update snprintf below188 * to allow longer names.189 */190 BUILD_BUG_ON(IFNAMSIZ != 16);191 snprintf(intf_name, sizeof(intf_name), "%.10s.%04x", ppriv->dev->name,192 pkey);193 194 ndev = ipoib_intf_alloc(ppriv->ca, ppriv->port, intf_name);195 if (IS_ERR(ndev)) {196 result = PTR_ERR(ndev);197 goto out;198 }199 priv = ipoib_priv(ndev);200 201 ndev->rtnl_link_ops = ipoib_get_link_ops();202 203 result = __ipoib_vlan_add(ppriv, priv, pkey, IPOIB_LEGACY_CHILD);204 205 if (result && ndev->reg_state == NETREG_UNINITIALIZED)206 free_netdev(ndev);207 208out:209 rtnl_unlock();210 211 return result;212}213 214struct ipoib_vlan_delete_work {215 struct work_struct work;216 struct net_device *dev;217};218 219/*220 * sysfs callbacks of a netdevice cannot obtain the rtnl lock as221 * unregister_netdev ultimately deletes the sysfs files while holding the rtnl222 * lock. This deadlocks the system.223 *224 * A callback can use rtnl_trylock to avoid the deadlock but it cannot call225 * unregister_netdev as that internally takes and releases the rtnl_lock. So226 * instead we find the netdev to unregister and then do the actual unregister227 * from the global work queue where we can obtain the rtnl_lock safely.228 */229static void ipoib_vlan_delete_task(struct work_struct *work)230{231 struct ipoib_vlan_delete_work *pwork =232 container_of(work, struct ipoib_vlan_delete_work, work);233 struct net_device *dev = pwork->dev;234 235 rtnl_lock();236 237 /* Unregistering tasks can race with another task or parent removal */238 if (dev->reg_state == NETREG_REGISTERED) {239 struct ipoib_dev_priv *priv = ipoib_priv(dev);240 struct ipoib_dev_priv *ppriv = ipoib_priv(priv->parent);241 242 ipoib_dbg(ppriv, "delete child vlan %s\n", dev->name);243 unregister_netdevice(dev);244 }245 246 rtnl_unlock();247 248 kfree(pwork);249}250 251int ipoib_vlan_delete(struct net_device *pdev, unsigned short pkey)252{253 struct ipoib_dev_priv *ppriv, *priv, *tpriv;254 int rc;255 256 if (!capable(CAP_NET_ADMIN))257 return -EPERM;258 259 if (!rtnl_trylock())260 return restart_syscall();261 262 if (pdev->reg_state != NETREG_REGISTERED) {263 rtnl_unlock();264 return -EPERM;265 }266 267 ppriv = ipoib_priv(pdev);268 269 rc = -ENODEV;270 list_for_each_entry_safe(priv, tpriv, &ppriv->child_intfs, list) {271 if (priv->pkey == pkey &&272 priv->child_type == IPOIB_LEGACY_CHILD) {273 struct ipoib_vlan_delete_work *work;274 275 work = kmalloc(sizeof(*work), GFP_KERNEL);276 if (!work) {277 rc = -ENOMEM;278 goto out;279 }280 281 down_write(&ppriv->vlan_rwsem);282 list_del_init(&priv->list);283 up_write(&ppriv->vlan_rwsem);284 work->dev = priv->dev;285 INIT_WORK(&work->work, ipoib_vlan_delete_task);286 queue_work(ipoib_workqueue, &work->work);287 288 rc = 0;289 break;290 }291 }292 293out:294 rtnl_unlock();295 296 return rc;297}298