diff options
Diffstat (limited to 'drivers/infiniband/ulp/ipoib/ipoib_vlan.c')
-rw-r--r-- | drivers/infiniband/ulp/ipoib/ipoib_vlan.c | 124 |
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 | } |
50 | static DEVICE_ATTR(parent, S_IRUGO, show_parent, NULL); | 50 | static DEVICE_ATTR(parent, S_IRUGO, show_parent, NULL); |
51 | 51 | ||
52 | int ipoib_vlan_add(struct net_device *pdev, unsigned short pkey) | 52 | int __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 | ||
144 | sysfs_failed: | 110 | sysfs_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 | ||
151 | err: | 118 | err: |
119 | return result; | ||
120 | } | ||
121 | |||
122 | int 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 | |||
165 | out: | ||
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; |