aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/ulp/ipoib/ipoib_vlan.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/infiniband/ulp/ipoib/ipoib_vlan.c')
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_vlan.c124
1 files changed, 70 insertions, 54 deletions
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_vlan.c b/drivers/infiniband/ulp/ipoib/ipoib_vlan.c
index d7e9740c7248..8292554bccb5 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_vlan.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_vlan.c
@@ -49,47 +49,11 @@ static ssize_t show_parent(struct device *d, struct device_attribute *attr,
49} 49}
50static DEVICE_ATTR(parent, S_IRUGO, show_parent, NULL); 50static DEVICE_ATTR(parent, S_IRUGO, show_parent, NULL);
51 51
52int ipoib_vlan_add(struct net_device *pdev, unsigned short pkey) 52int __ipoib_vlan_add(struct ipoib_dev_priv *ppriv, struct ipoib_dev_priv *priv,
53 u16 pkey, int type)
53{ 54{
54 struct ipoib_dev_priv *ppriv, *priv;
55 char intf_name[IFNAMSIZ];
56 int result; 55 int result;
57 56
58 if (!capable(CAP_NET_ADMIN))
59 return -EPERM;
60
61 ppriv = netdev_priv(pdev);
62
63 if (!rtnl_trylock())
64 return restart_syscall();
65 mutex_lock(&ppriv->vlan_mutex);
66
67 /*
68 * First ensure this isn't a duplicate. We check the parent device and
69 * then all of the child interfaces to make sure the Pkey doesn't match.
70 */
71 if (ppriv->pkey == pkey) {
72 result = -ENOTUNIQ;
73 priv = NULL;
74 goto err;
75 }
76
77 list_for_each_entry(priv, &ppriv->child_intfs, list) {
78 if (priv->pkey == pkey) {
79 result = -ENOTUNIQ;
80 priv = NULL;
81 goto err;
82 }
83 }
84
85 snprintf(intf_name, sizeof intf_name, "%s.%04x",
86 ppriv->dev->name, pkey);
87 priv = ipoib_intf_alloc(intf_name);
88 if (!priv) {
89 result = -ENOMEM;
90 goto err;
91 }
92
93 priv->max_ib_mtu = ppriv->max_ib_mtu; 57 priv->max_ib_mtu = ppriv->max_ib_mtu;
94 /* MTU will be reset when mcast join happens */ 58 /* MTU will be reset when mcast join happens */
95 priv->dev->mtu = IPOIB_UD_MTU(priv->max_ib_mtu); 59 priv->dev->mtu = IPOIB_UD_MTU(priv->max_ib_mtu);
@@ -124,24 +88,27 @@ int ipoib_vlan_add(struct net_device *pdev, unsigned short pkey)
124 88
125 ipoib_create_debug_files(priv->dev); 89 ipoib_create_debug_files(priv->dev);
126 90
127 if (ipoib_cm_add_mode_attr(priv->dev)) 91 /* RTNL childs don't need proprietary sysfs entries */
128 goto sysfs_failed; 92 if (type == IPOIB_LEGACY_CHILD) {
129 if (ipoib_add_pkey_attr(priv->dev)) 93 if (ipoib_cm_add_mode_attr(priv->dev))
130 goto sysfs_failed; 94 goto sysfs_failed;
131 if (ipoib_add_umcast_attr(priv->dev)) 95 if (ipoib_add_pkey_attr(priv->dev))
132 goto sysfs_failed; 96 goto sysfs_failed;
133 97 if (ipoib_add_umcast_attr(priv->dev))
134 if (device_create_file(&priv->dev->dev, &dev_attr_parent)) 98 goto sysfs_failed;
135 goto sysfs_failed; 99
100 if (device_create_file(&priv->dev->dev, &dev_attr_parent))
101 goto sysfs_failed;
102 }
136 103
104 priv->child_type = type;
105 priv->dev->iflink = ppriv->dev->ifindex;
137 list_add_tail(&priv->list, &ppriv->child_intfs); 106 list_add_tail(&priv->list, &ppriv->child_intfs);
138 107
139 mutex_unlock(&ppriv->vlan_mutex);
140 rtnl_unlock();
141
142 return 0; 108 return 0;
143 109
144sysfs_failed: 110sysfs_failed:
111 result = -ENOMEM;
145 ipoib_delete_debug_files(priv->dev); 112 ipoib_delete_debug_files(priv->dev);
146 unregister_netdevice(priv->dev); 113 unregister_netdevice(priv->dev);
147 114
@@ -149,11 +116,60 @@ register_failed:
149 ipoib_dev_cleanup(priv->dev); 116 ipoib_dev_cleanup(priv->dev);
150 117
151err: 118err:
119 return result;
120}
121
122int ipoib_vlan_add(struct net_device *pdev, unsigned short pkey)
123{
124 struct ipoib_dev_priv *ppriv, *priv;
125 char intf_name[IFNAMSIZ];
126 struct ipoib_dev_priv *tpriv;
127 int result;
128
129 if (!capable(CAP_NET_ADMIN))
130 return -EPERM;
131
132 ppriv = netdev_priv(pdev);
133
134 snprintf(intf_name, sizeof intf_name, "%s.%04x",
135 ppriv->dev->name, pkey);
136 priv = ipoib_intf_alloc(intf_name);
137 if (!priv)
138 return -ENOMEM;
139
140 if (!rtnl_trylock())
141 return restart_syscall();
142
143 mutex_lock(&ppriv->vlan_mutex);
144
145 /*
146 * First ensure this isn't a duplicate. We check the parent device and
147 * then all of the legacy child interfaces to make sure the Pkey
148 * doesn't match.
149 */
150 if (ppriv->pkey == pkey) {
151 result = -ENOTUNIQ;
152 goto out;
153 }
154
155 list_for_each_entry(tpriv, &ppriv->child_intfs, list) {
156 if (tpriv->pkey == pkey &&
157 tpriv->child_type == IPOIB_LEGACY_CHILD) {
158 result = -ENOTUNIQ;
159 goto out;
160 }
161 }
162
163 result = __ipoib_vlan_add(ppriv, priv, pkey, IPOIB_LEGACY_CHILD);
164
165out:
152 mutex_unlock(&ppriv->vlan_mutex); 166 mutex_unlock(&ppriv->vlan_mutex);
153 rtnl_unlock(); 167
154 if (priv) 168 if (result)
155 free_netdev(priv->dev); 169 free_netdev(priv->dev);
156 170
171 rtnl_unlock();
172
157 return result; 173 return result;
158} 174}
159 175
@@ -171,9 +187,9 @@ int ipoib_vlan_delete(struct net_device *pdev, unsigned short pkey)
171 return restart_syscall(); 187 return restart_syscall();
172 mutex_lock(&ppriv->vlan_mutex); 188 mutex_lock(&ppriv->vlan_mutex);
173 list_for_each_entry_safe(priv, tpriv, &ppriv->child_intfs, list) { 189 list_for_each_entry_safe(priv, tpriv, &ppriv->child_intfs, list) {
174 if (priv->pkey == pkey) { 190 if (priv->pkey == pkey &&
191 priv->child_type == IPOIB_LEGACY_CHILD) {
175 unregister_netdevice(priv->dev); 192 unregister_netdevice(priv->dev);
176 ipoib_dev_cleanup(priv->dev);
177 list_del(&priv->list); 193 list_del(&priv->list);
178 dev = priv->dev; 194 dev = priv->dev;
179 break; 195 break;