Path: blob/master/drivers/infiniband/ulp/ipoib/ipoib_vlan.c
15112 views
/*1* Copyright (c) 2004 Topspin Communications. All rights reserved.2*3* This software is available to you under a choice of one of two4* licenses. You may choose to be licensed under the terms of the GNU5* General Public License (GPL) Version 2, available from the file6* COPYING in the main directory of this source tree, or the7* OpenIB.org BSD license below:8*9* Redistribution and use in source and binary forms, with or10* without modification, are permitted provided that the following11* conditions are met:12*13* - Redistributions of source code must retain the above14* copyright notice, this list of conditions and the following15* disclaimer.16*17* - Redistributions in binary form must reproduce the above18* copyright notice, this list of conditions and the following19* disclaimer in the documentation and/or other materials20* provided with the distribution.21*22* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,23* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF24* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND25* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS26* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN27* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN28* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE29* SOFTWARE.30*/3132#include <linux/module.h>3334#include <linux/init.h>35#include <linux/seq_file.h>3637#include <asm/uaccess.h>3839#include "ipoib.h"4041static ssize_t show_parent(struct device *d, struct device_attribute *attr,42char *buf)43{44struct net_device *dev = to_net_dev(d);45struct ipoib_dev_priv *priv = netdev_priv(dev);4647return sprintf(buf, "%s\n", priv->parent->name);48}49static DEVICE_ATTR(parent, S_IRUGO, show_parent, NULL);5051int ipoib_vlan_add(struct net_device *pdev, unsigned short pkey)52{53struct ipoib_dev_priv *ppriv, *priv;54char intf_name[IFNAMSIZ];55int result;5657if (!capable(CAP_NET_ADMIN))58return -EPERM;5960ppriv = netdev_priv(pdev);6162if (!rtnl_trylock())63return restart_syscall();64mutex_lock(&ppriv->vlan_mutex);6566/*67* First ensure this isn't a duplicate. We check the parent device and68* then all of the child interfaces to make sure the Pkey doesn't match.69*/70if (ppriv->pkey == pkey) {71result = -ENOTUNIQ;72priv = NULL;73goto err;74}7576list_for_each_entry(priv, &ppriv->child_intfs, list) {77if (priv->pkey == pkey) {78result = -ENOTUNIQ;79priv = NULL;80goto err;81}82}8384snprintf(intf_name, sizeof intf_name, "%s.%04x",85ppriv->dev->name, pkey);86priv = ipoib_intf_alloc(intf_name);87if (!priv) {88result = -ENOMEM;89goto err;90}9192priv->max_ib_mtu = ppriv->max_ib_mtu;93/* MTU will be reset when mcast join happens */94priv->dev->mtu = IPOIB_UD_MTU(priv->max_ib_mtu);95priv->mcast_mtu = priv->admin_mtu = priv->dev->mtu;96set_bit(IPOIB_FLAG_SUBINTERFACE, &priv->flags);9798result = ipoib_set_dev_features(priv, ppriv->ca);99if (result)100goto err;101102priv->pkey = pkey;103104memcpy(priv->dev->dev_addr, ppriv->dev->dev_addr, INFINIBAND_ALEN);105priv->dev->broadcast[8] = pkey >> 8;106priv->dev->broadcast[9] = pkey & 0xff;107108result = ipoib_dev_init(priv->dev, ppriv->ca, ppriv->port);109if (result < 0) {110ipoib_warn(ppriv, "failed to initialize subinterface: "111"device %s, port %d",112ppriv->ca->name, ppriv->port);113goto err;114}115116result = register_netdevice(priv->dev);117if (result) {118ipoib_warn(priv, "failed to initialize; error %i", result);119goto register_failed;120}121122priv->parent = ppriv->dev;123124ipoib_create_debug_files(priv->dev);125126if (ipoib_cm_add_mode_attr(priv->dev))127goto sysfs_failed;128if (ipoib_add_pkey_attr(priv->dev))129goto sysfs_failed;130if (ipoib_add_umcast_attr(priv->dev))131goto sysfs_failed;132133if (device_create_file(&priv->dev->dev, &dev_attr_parent))134goto sysfs_failed;135136list_add_tail(&priv->list, &ppriv->child_intfs);137138mutex_unlock(&ppriv->vlan_mutex);139rtnl_unlock();140141return 0;142143sysfs_failed:144ipoib_delete_debug_files(priv->dev);145unregister_netdevice(priv->dev);146147register_failed:148ipoib_dev_cleanup(priv->dev);149150err:151mutex_unlock(&ppriv->vlan_mutex);152rtnl_unlock();153if (priv)154free_netdev(priv->dev);155156return result;157}158159int ipoib_vlan_delete(struct net_device *pdev, unsigned short pkey)160{161struct ipoib_dev_priv *ppriv, *priv, *tpriv;162struct net_device *dev = NULL;163164if (!capable(CAP_NET_ADMIN))165return -EPERM;166167ppriv = netdev_priv(pdev);168169if (!rtnl_trylock())170return restart_syscall();171mutex_lock(&ppriv->vlan_mutex);172list_for_each_entry_safe(priv, tpriv, &ppriv->child_intfs, list) {173if (priv->pkey == pkey) {174unregister_netdevice(priv->dev);175ipoib_dev_cleanup(priv->dev);176list_del(&priv->list);177dev = priv->dev;178break;179}180}181mutex_unlock(&ppriv->vlan_mutex);182rtnl_unlock();183184if (dev) {185free_netdev(dev);186return 0;187}188189return -ENODEV;190}191192193