root/drivers/infiniband/ulp/ipoib/ipoib_vlan.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. show_parent
  2. is_child_unique
  3. __ipoib_vlan_add
  4. ipoib_vlan_add
  5. ipoib_vlan_delete_task
  6. ipoib_vlan_delete

   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/module.h>
  34 #include <linux/sched/signal.h>
  35 
  36 #include <linux/init.h>
  37 #include <linux/seq_file.h>
  38 
  39 #include <linux/uaccess.h>
  40 
  41 #include "ipoib.h"
  42 
  43 static ssize_t show_parent(struct device *d, struct device_attribute *attr,
  44                            char *buf)
  45 {
  46         struct net_device *dev = to_net_dev(d);
  47         struct ipoib_dev_priv *priv = ipoib_priv(dev);
  48 
  49         return sprintf(buf, "%s\n", priv->parent->name);
  50 }
  51 static DEVICE_ATTR(parent, S_IRUGO, show_parent, NULL);
  52 
  53 static bool is_child_unique(struct ipoib_dev_priv *ppriv,
  54                             struct ipoib_dev_priv *priv)
  55 {
  56         struct ipoib_dev_priv *tpriv;
  57 
  58         ASSERT_RTNL();
  59 
  60         /*
  61          * Since the legacy sysfs interface uses pkey for deletion it cannot
  62          * support more than one interface with the same pkey, it creates
  63          * ambiguity.  The RTNL interface deletes using the netdev so it does
  64          * not have a problem to support duplicated pkeys.
  65          */
  66         if (priv->child_type != IPOIB_LEGACY_CHILD)
  67                 return true;
  68 
  69         /*
  70          * First ensure this isn't a duplicate. We check the parent device and
  71          * then all of the legacy child interfaces to make sure the Pkey
  72          * doesn't match.
  73          */
  74         if (ppriv->pkey == priv->pkey)
  75                 return false;
  76 
  77         list_for_each_entry(tpriv, &ppriv->child_intfs, list) {
  78                 if (tpriv->pkey == priv->pkey &&
  79                     tpriv->child_type == IPOIB_LEGACY_CHILD)
  80                         return false;
  81         }
  82 
  83         return true;
  84 }
  85 
  86 /*
  87  * NOTE: If this function fails then the priv->dev will remain valid, however
  88  * priv will have been freed and must not be touched by caller in the error
  89  * case.
  90  *
  91  * If (ndev->reg_state == NETREG_UNINITIALIZED) then it is up to the caller to
  92  * free the net_device (just as rtnl_newlink does) otherwise the net_device
  93  * will be freed when the rtnl is unlocked.
  94  */
  95 int __ipoib_vlan_add(struct ipoib_dev_priv *ppriv, struct ipoib_dev_priv *priv,
  96                      u16 pkey, int type)
  97 {
  98         struct net_device *ndev = priv->dev;
  99         int result;
 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         priv->parent = ppriv->dev;
 121         priv->pkey = pkey;
 122         priv->child_type = type;
 123 
 124         if (!is_child_unique(ppriv, priv)) {
 125                 result = -ENOTUNIQ;
 126                 goto out_early;
 127         }
 128 
 129         result = register_netdevice(ndev);
 130         if (result) {
 131                 ipoib_warn(priv, "failed to initialize; error %i", result);
 132 
 133                 /*
 134                  * register_netdevice sometimes calls priv_destructor,
 135                  * sometimes not. Make sure it was done.
 136                  */
 137                 goto out_early;
 138         }
 139 
 140         /* RTNL childs don't need proprietary sysfs entries */
 141         if (type == IPOIB_LEGACY_CHILD) {
 142                 if (ipoib_cm_add_mode_attr(ndev))
 143                         goto sysfs_failed;
 144                 if (ipoib_add_pkey_attr(ndev))
 145                         goto sysfs_failed;
 146                 if (ipoib_add_umcast_attr(ndev))
 147                         goto sysfs_failed;
 148 
 149                 if (device_create_file(&ndev->dev, &dev_attr_parent))
 150                         goto sysfs_failed;
 151         }
 152 
 153         return 0;
 154 
 155 sysfs_failed:
 156         unregister_netdevice(priv->dev);
 157         return -ENOMEM;
 158 
 159 out_early:
 160         if (ndev->priv_destructor)
 161                 ndev->priv_destructor(ndev);
 162         return result;
 163 }
 164 
 165 int ipoib_vlan_add(struct net_device *pdev, unsigned short pkey)
 166 {
 167         struct ipoib_dev_priv *ppriv, *priv;
 168         char intf_name[IFNAMSIZ];
 169         struct net_device *ndev;
 170         int result;
 171 
 172         if (!capable(CAP_NET_ADMIN))
 173                 return -EPERM;
 174 
 175         if (!rtnl_trylock())
 176                 return restart_syscall();
 177 
 178         if (pdev->reg_state != NETREG_REGISTERED) {
 179                 rtnl_unlock();
 180                 return -EPERM;
 181         }
 182 
 183         ppriv = ipoib_priv(pdev);
 184 
 185         snprintf(intf_name, sizeof(intf_name), "%s.%04x",
 186                  ppriv->dev->name, pkey);
 187 
 188         ndev = ipoib_intf_alloc(ppriv->ca, ppriv->port, intf_name);
 189         if (IS_ERR(ndev)) {
 190                 result = PTR_ERR(ndev);
 191                 goto out;
 192         }
 193         priv = ipoib_priv(ndev);
 194 
 195         result = __ipoib_vlan_add(ppriv, priv, pkey, IPOIB_LEGACY_CHILD);
 196 
 197         if (result && ndev->reg_state == NETREG_UNINITIALIZED)
 198                 free_netdev(ndev);
 199 
 200 out:
 201         rtnl_unlock();
 202 
 203         return result;
 204 }
 205 
 206 struct ipoib_vlan_delete_work {
 207         struct work_struct work;
 208         struct net_device *dev;
 209 };
 210 
 211 /*
 212  * sysfs callbacks of a netdevice cannot obtain the rtnl lock as
 213  * unregister_netdev ultimately deletes the sysfs files while holding the rtnl
 214  * lock. This deadlocks the system.
 215  *
 216  * A callback can use rtnl_trylock to avoid the deadlock but it cannot call
 217  * unregister_netdev as that internally takes and releases the rtnl_lock.  So
 218  * instead we find the netdev to unregister and then do the actual unregister
 219  * from the global work queue where we can obtain the rtnl_lock safely.
 220  */
 221 static void ipoib_vlan_delete_task(struct work_struct *work)
 222 {
 223         struct ipoib_vlan_delete_work *pwork =
 224                 container_of(work, struct ipoib_vlan_delete_work, work);
 225         struct net_device *dev = pwork->dev;
 226 
 227         rtnl_lock();
 228 
 229         /* Unregistering tasks can race with another task or parent removal */
 230         if (dev->reg_state == NETREG_REGISTERED) {
 231                 struct ipoib_dev_priv *priv = ipoib_priv(dev);
 232                 struct ipoib_dev_priv *ppriv = ipoib_priv(priv->parent);
 233 
 234                 ipoib_dbg(ppriv, "delete child vlan %s\n", dev->name);
 235                 unregister_netdevice(dev);
 236         }
 237 
 238         rtnl_unlock();
 239 
 240         kfree(pwork);
 241 }
 242 
 243 int ipoib_vlan_delete(struct net_device *pdev, unsigned short pkey)
 244 {
 245         struct ipoib_dev_priv *ppriv, *priv, *tpriv;
 246         int rc;
 247 
 248         if (!capable(CAP_NET_ADMIN))
 249                 return -EPERM;
 250 
 251         if (!rtnl_trylock())
 252                 return restart_syscall();
 253 
 254         if (pdev->reg_state != NETREG_REGISTERED) {
 255                 rtnl_unlock();
 256                 return -EPERM;
 257         }
 258 
 259         ppriv = ipoib_priv(pdev);
 260 
 261         rc = -ENODEV;
 262         list_for_each_entry_safe(priv, tpriv, &ppriv->child_intfs, list) {
 263                 if (priv->pkey == pkey &&
 264                     priv->child_type == IPOIB_LEGACY_CHILD) {
 265                         struct ipoib_vlan_delete_work *work;
 266 
 267                         work = kmalloc(sizeof(*work), GFP_KERNEL);
 268                         if (!work) {
 269                                 rc = -ENOMEM;
 270                                 goto out;
 271                         }
 272 
 273                         down_write(&ppriv->vlan_rwsem);
 274                         list_del_init(&priv->list);
 275                         up_write(&ppriv->vlan_rwsem);
 276                         work->dev = priv->dev;
 277                         INIT_WORK(&work->work, ipoib_vlan_delete_task);
 278                         queue_work(ipoib_workqueue, &work->work);
 279 
 280                         rc = 0;
 281                         break;
 282                 }
 283         }
 284 
 285 out:
 286         rtnl_unlock();
 287 
 288         return rc;
 289 }

/* [<][>][^][v][top][bottom][index][help] */