11da177e4SLinus Torvalds /*
21da177e4SLinus Torvalds * Copyright (c) 2004 Topspin Communications. All rights reserved.
31da177e4SLinus Torvalds *
41da177e4SLinus Torvalds * This software is available to you under a choice of one of two
51da177e4SLinus Torvalds * licenses. You may choose to be licensed under the terms of the GNU
61da177e4SLinus Torvalds * General Public License (GPL) Version 2, available from the file
71da177e4SLinus Torvalds * COPYING in the main directory of this source tree, or the
81da177e4SLinus Torvalds * OpenIB.org BSD license below:
91da177e4SLinus Torvalds *
101da177e4SLinus Torvalds * Redistribution and use in source and binary forms, with or
111da177e4SLinus Torvalds * without modification, are permitted provided that the following
121da177e4SLinus Torvalds * conditions are met:
131da177e4SLinus Torvalds *
141da177e4SLinus Torvalds * - Redistributions of source code must retain the above
151da177e4SLinus Torvalds * copyright notice, this list of conditions and the following
161da177e4SLinus Torvalds * disclaimer.
171da177e4SLinus Torvalds *
181da177e4SLinus Torvalds * - Redistributions in binary form must reproduce the above
191da177e4SLinus Torvalds * copyright notice, this list of conditions and the following
201da177e4SLinus Torvalds * disclaimer in the documentation and/or other materials
211da177e4SLinus Torvalds * provided with the distribution.
221da177e4SLinus Torvalds *
231da177e4SLinus Torvalds * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
241da177e4SLinus Torvalds * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
251da177e4SLinus Torvalds * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
261da177e4SLinus Torvalds * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
271da177e4SLinus Torvalds * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
281da177e4SLinus Torvalds * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
291da177e4SLinus Torvalds * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
301da177e4SLinus Torvalds * SOFTWARE.
311da177e4SLinus Torvalds */
321da177e4SLinus Torvalds
33174cd4b1SIngo Molnar #include <linux/sched/signal.h>
341da177e4SLinus Torvalds
351da177e4SLinus Torvalds #include <linux/init.h>
361da177e4SLinus Torvalds #include <linux/seq_file.h>
371da177e4SLinus Torvalds
387c0f6ba6SLinus Torvalds #include <linux/uaccess.h>
391da177e4SLinus Torvalds
401da177e4SLinus Torvalds #include "ipoib.h"
411da177e4SLinus Torvalds
parent_show(struct device * d,struct device_attribute * attr,char * buf)421f8f60f3SYueHaibing static ssize_t parent_show(struct device *d, struct device_attribute *attr,
4343cb76d9SGreg Kroah-Hartman char *buf)
441da177e4SLinus Torvalds {
4543cb76d9SGreg Kroah-Hartman struct net_device *dev = to_net_dev(d);
46c1048affSErez Shitrit struct ipoib_dev_priv *priv = ipoib_priv(dev);
471da177e4SLinus Torvalds
481c7fd726SJoe Perches return sysfs_emit(buf, "%s\n", priv->parent->name);
491da177e4SLinus Torvalds }
501f8f60f3SYueHaibing static DEVICE_ATTR_RO(parent);
511da177e4SLinus Torvalds
is_child_unique(struct ipoib_dev_priv * ppriv,struct ipoib_dev_priv * priv)5276010976SJason Gunthorpe static bool is_child_unique(struct ipoib_dev_priv *ppriv,
5376010976SJason Gunthorpe struct ipoib_dev_priv *priv)
5476010976SJason Gunthorpe {
5576010976SJason Gunthorpe struct ipoib_dev_priv *tpriv;
5676010976SJason Gunthorpe
5776010976SJason Gunthorpe ASSERT_RTNL();
5876010976SJason Gunthorpe
5976010976SJason Gunthorpe /*
6076010976SJason Gunthorpe * Since the legacy sysfs interface uses pkey for deletion it cannot
6176010976SJason Gunthorpe * support more than one interface with the same pkey, it creates
6276010976SJason Gunthorpe * ambiguity. The RTNL interface deletes using the netdev so it does
6376010976SJason Gunthorpe * not have a problem to support duplicated pkeys.
6476010976SJason Gunthorpe */
6576010976SJason Gunthorpe if (priv->child_type != IPOIB_LEGACY_CHILD)
6676010976SJason Gunthorpe return true;
6776010976SJason Gunthorpe
6876010976SJason Gunthorpe /*
6976010976SJason Gunthorpe * First ensure this isn't a duplicate. We check the parent device and
7076010976SJason Gunthorpe * then all of the legacy child interfaces to make sure the Pkey
7176010976SJason Gunthorpe * doesn't match.
7276010976SJason Gunthorpe */
7376010976SJason Gunthorpe if (ppriv->pkey == priv->pkey)
7476010976SJason Gunthorpe return false;
7576010976SJason Gunthorpe
7676010976SJason Gunthorpe list_for_each_entry(tpriv, &ppriv->child_intfs, list) {
7776010976SJason Gunthorpe if (tpriv->pkey == priv->pkey &&
7876010976SJason Gunthorpe tpriv->child_type == IPOIB_LEGACY_CHILD)
7976010976SJason Gunthorpe return false;
8076010976SJason Gunthorpe }
8176010976SJason Gunthorpe
8276010976SJason Gunthorpe return true;
8376010976SJason Gunthorpe }
8476010976SJason Gunthorpe
859f49a5b5SJason Gunthorpe /*
869f49a5b5SJason Gunthorpe * NOTE: If this function fails then the priv->dev will remain valid, however
875d6b0cb3SDenis Drozdov * priv will have been freed and must not be touched by caller in the error
889f49a5b5SJason Gunthorpe * case.
899f49a5b5SJason Gunthorpe *
909f49a5b5SJason Gunthorpe * If (ndev->reg_state == NETREG_UNINITIALIZED) then it is up to the caller to
919f49a5b5SJason Gunthorpe * free the net_device (just as rtnl_newlink does) otherwise the net_device
929f49a5b5SJason Gunthorpe * will be freed when the rtnl is unlocked.
939f49a5b5SJason Gunthorpe */
__ipoib_vlan_add(struct ipoib_dev_priv * ppriv,struct ipoib_dev_priv * priv,u16 pkey,int type)949baa0b03SOr Gerlitz int __ipoib_vlan_add(struct ipoib_dev_priv *ppriv, struct ipoib_dev_priv *priv,
959baa0b03SOr Gerlitz u16 pkey, int type)
961da177e4SLinus Torvalds {
979f49a5b5SJason Gunthorpe struct net_device *ndev = priv->dev;
981da177e4SLinus Torvalds int result;
99b7e159ebSGary Leshner struct rdma_netdev *rn = netdev_priv(ndev);
1001da177e4SLinus Torvalds
1019f49a5b5SJason Gunthorpe ASSERT_RTNL();
1029f49a5b5SJason Gunthorpe
10325405d98SJason Gunthorpe /*
1045d6b0cb3SDenis Drozdov * We do not need to touch priv if register_netdevice fails, so just
1055d6b0cb3SDenis Drozdov * always use this flow.
1065d6b0cb3SDenis Drozdov */
1075d6b0cb3SDenis Drozdov ndev->priv_destructor = ipoib_intf_free;
1085d6b0cb3SDenis Drozdov
1095d6b0cb3SDenis Drozdov /*
11025405d98SJason Gunthorpe * Racing with unregister of the parent must be prevented by the
11125405d98SJason Gunthorpe * caller.
11225405d98SJason Gunthorpe */
11325405d98SJason Gunthorpe WARN_ON(ppriv->dev->reg_state != NETREG_REGISTERED);
11425405d98SJason Gunthorpe
11576010976SJason Gunthorpe if (pkey == 0 || pkey == 0x8000) {
11676010976SJason Gunthorpe result = -EINVAL;
11776010976SJason Gunthorpe goto out_early;
11876010976SJason Gunthorpe }
11976010976SJason Gunthorpe
120b7e159ebSGary Leshner rn->mtu = priv->mcast_mtu;
121b7e159ebSGary Leshner
1222c153959SErez Shitrit priv->parent = ppriv->dev;
1231da177e4SLinus Torvalds priv->pkey = pkey;
124eaeb3984SJason Gunthorpe priv->child_type = type;
1251da177e4SLinus Torvalds
12676010976SJason Gunthorpe if (!is_child_unique(ppriv, priv)) {
12776010976SJason Gunthorpe result = -ENOTUNIQ;
12876010976SJason Gunthorpe goto out_early;
12976010976SJason Gunthorpe }
13076010976SJason Gunthorpe
1319f49a5b5SJason Gunthorpe result = register_netdevice(ndev);
1321da177e4SLinus Torvalds if (result) {
1331da177e4SLinus Torvalds ipoib_warn(priv, "failed to initialize; error %i", result);
1349f49a5b5SJason Gunthorpe
1359f49a5b5SJason Gunthorpe /*
1369f49a5b5SJason Gunthorpe * register_netdevice sometimes calls priv_destructor,
1379f49a5b5SJason Gunthorpe * sometimes not. Make sure it was done.
1389f49a5b5SJason Gunthorpe */
13976010976SJason Gunthorpe goto out_early;
1401da177e4SLinus Torvalds }
1411da177e4SLinus Torvalds
142862096a8SOr Gerlitz /* RTNL childs don't need proprietary sysfs entries */
143862096a8SOr Gerlitz if (type == IPOIB_LEGACY_CHILD) {
1449f49a5b5SJason Gunthorpe if (ipoib_cm_add_mode_attr(ndev))
145839fcabaSMichael S. Tsirkin goto sysfs_failed;
1469f49a5b5SJason Gunthorpe if (ipoib_add_pkey_attr(ndev))
1471da177e4SLinus Torvalds goto sysfs_failed;
1489f49a5b5SJason Gunthorpe if (ipoib_add_umcast_attr(ndev))
149335a64a5SOr Gerlitz goto sysfs_failed;
1501da177e4SLinus Torvalds
1519f49a5b5SJason Gunthorpe if (device_create_file(&ndev->dev, &dev_attr_parent))
1521da177e4SLinus Torvalds goto sysfs_failed;
153862096a8SOr Gerlitz }
1541da177e4SLinus Torvalds
1551da177e4SLinus Torvalds return 0;
1561da177e4SLinus Torvalds
1571da177e4SLinus Torvalds sysfs_failed:
158cbbe1efaSRoland Dreier unregister_netdevice(priv->dev);
159eaeb3984SJason Gunthorpe return -ENOMEM;
16076010976SJason Gunthorpe
16176010976SJason Gunthorpe out_early:
16276010976SJason Gunthorpe if (ndev->priv_destructor)
16376010976SJason Gunthorpe ndev->priv_destructor(ndev);
16476010976SJason Gunthorpe return result;
1659baa0b03SOr Gerlitz }
1669baa0b03SOr Gerlitz
ipoib_vlan_add(struct net_device * pdev,unsigned short pkey)1679baa0b03SOr Gerlitz int ipoib_vlan_add(struct net_device *pdev, unsigned short pkey)
1689baa0b03SOr Gerlitz {
1699baa0b03SOr Gerlitz struct ipoib_dev_priv *ppriv, *priv;
1709baa0b03SOr Gerlitz char intf_name[IFNAMSIZ];
1719f49a5b5SJason Gunthorpe struct net_device *ndev;
1729baa0b03SOr Gerlitz int result;
1739baa0b03SOr Gerlitz
1749baa0b03SOr Gerlitz if (!capable(CAP_NET_ADMIN))
1759baa0b03SOr Gerlitz return -EPERM;
1769baa0b03SOr Gerlitz
177ee190ab7SJason Gunthorpe if (!rtnl_trylock())
1784542d66bSFeras Daoud return restart_syscall();
1794542d66bSFeras Daoud
180577e07ffSJason Gunthorpe if (pdev->reg_state != NETREG_REGISTERED) {
181577e07ffSJason Gunthorpe rtnl_unlock();
182577e07ffSJason Gunthorpe return -EPERM;
183577e07ffSJason Gunthorpe }
184577e07ffSJason Gunthorpe
18576010976SJason Gunthorpe ppriv = ipoib_priv(pdev);
1869baa0b03SOr Gerlitz
187e011ea68SLeon Romanovsky /* If you increase IFNAMSIZ, update snprintf below
188e011ea68SLeon Romanovsky * to allow longer names.
189e011ea68SLeon Romanovsky */
190e011ea68SLeon Romanovsky BUILD_BUG_ON(IFNAMSIZ != 16);
191e011ea68SLeon Romanovsky snprintf(intf_name, sizeof(intf_name), "%.10s.%04x", ppriv->dev->name,
192e011ea68SLeon Romanovsky pkey);
1939baa0b03SOr Gerlitz
1945d6b0cb3SDenis Drozdov ndev = ipoib_intf_alloc(ppriv->ca, ppriv->port, intf_name);
1955d6b0cb3SDenis Drozdov if (IS_ERR(ndev)) {
1965d6b0cb3SDenis Drozdov result = PTR_ERR(ndev);
1979f49a5b5SJason Gunthorpe goto out;
1989f49a5b5SJason Gunthorpe }
1995d6b0cb3SDenis Drozdov priv = ipoib_priv(ndev);
2009f49a5b5SJason Gunthorpe
2015ce2dcedSKamal Heib ndev->rtnl_link_ops = ipoib_get_link_ops();
2025ce2dcedSKamal Heib
2039baa0b03SOr Gerlitz result = __ipoib_vlan_add(ppriv, priv, pkey, IPOIB_LEGACY_CHILD);
2049baa0b03SOr Gerlitz
2059f49a5b5SJason Gunthorpe if (result && ndev->reg_state == NETREG_UNINITIALIZED)
2069f49a5b5SJason Gunthorpe free_netdev(ndev);
2079f49a5b5SJason Gunthorpe
2089baa0b03SOr Gerlitz out:
20989a3987aSFeras Daoud rtnl_unlock();
21089a3987aSFeras Daoud
2111da177e4SLinus Torvalds return result;
2121da177e4SLinus Torvalds }
2131da177e4SLinus Torvalds
214ee190ab7SJason Gunthorpe struct ipoib_vlan_delete_work {
215ee190ab7SJason Gunthorpe struct work_struct work;
216ee190ab7SJason Gunthorpe struct net_device *dev;
217ee190ab7SJason Gunthorpe };
218ee190ab7SJason Gunthorpe
219ee190ab7SJason Gunthorpe /*
220ee190ab7SJason Gunthorpe * sysfs callbacks of a netdevice cannot obtain the rtnl lock as
221ee190ab7SJason Gunthorpe * unregister_netdev ultimately deletes the sysfs files while holding the rtnl
222ee190ab7SJason Gunthorpe * lock. This deadlocks the system.
223ee190ab7SJason Gunthorpe *
224ee190ab7SJason Gunthorpe * A callback can use rtnl_trylock to avoid the deadlock but it cannot call
225ee190ab7SJason Gunthorpe * unregister_netdev as that internally takes and releases the rtnl_lock. So
226ee190ab7SJason Gunthorpe * instead we find the netdev to unregister and then do the actual unregister
227ee190ab7SJason Gunthorpe * from the global work queue where we can obtain the rtnl_lock safely.
228ee190ab7SJason Gunthorpe */
ipoib_vlan_delete_task(struct work_struct * work)229ee190ab7SJason Gunthorpe static void ipoib_vlan_delete_task(struct work_struct *work)
2301da177e4SLinus Torvalds {
231ee190ab7SJason Gunthorpe struct ipoib_vlan_delete_work *pwork =
232ee190ab7SJason Gunthorpe container_of(work, struct ipoib_vlan_delete_work, work);
233ee190ab7SJason Gunthorpe struct net_device *dev = pwork->dev;
2341da177e4SLinus Torvalds
235ee190ab7SJason Gunthorpe rtnl_lock();
2361da177e4SLinus Torvalds
237ee190ab7SJason Gunthorpe /* Unregistering tasks can race with another task or parent removal */
238ee190ab7SJason Gunthorpe if (dev->reg_state == NETREG_REGISTERED) {
239ee190ab7SJason Gunthorpe struct ipoib_dev_priv *priv = ipoib_priv(dev);
240ee190ab7SJason Gunthorpe struct ipoib_dev_priv *ppriv = ipoib_priv(priv->parent);
2411da177e4SLinus Torvalds
2421c3098cdSFeras Daoud ipoib_dbg(ppriv, "delete child vlan %s\n", dev->name);
2431c3098cdSFeras Daoud unregister_netdevice(dev);
2441c3098cdSFeras Daoud }
2451c3098cdSFeras Daoud
246cbbe1efaSRoland Dreier rtnl_unlock();
2471da177e4SLinus Torvalds
248ee190ab7SJason Gunthorpe kfree(pwork);
249ee190ab7SJason Gunthorpe }
250ee190ab7SJason Gunthorpe
ipoib_vlan_delete(struct net_device * pdev,unsigned short pkey)251ee190ab7SJason Gunthorpe int ipoib_vlan_delete(struct net_device *pdev, unsigned short pkey)
252ee190ab7SJason Gunthorpe {
253ee190ab7SJason Gunthorpe struct ipoib_dev_priv *ppriv, *priv, *tpriv;
254ee190ab7SJason Gunthorpe int rc;
255ee190ab7SJason Gunthorpe
256ee190ab7SJason Gunthorpe if (!capable(CAP_NET_ADMIN))
257ee190ab7SJason Gunthorpe return -EPERM;
258ee190ab7SJason Gunthorpe
259ee190ab7SJason Gunthorpe if (!rtnl_trylock())
260ee190ab7SJason Gunthorpe return restart_syscall();
261ee190ab7SJason Gunthorpe
262ee190ab7SJason Gunthorpe if (pdev->reg_state != NETREG_REGISTERED) {
263ee190ab7SJason Gunthorpe rtnl_unlock();
264ee190ab7SJason Gunthorpe return -EPERM;
265ee190ab7SJason Gunthorpe }
266ee190ab7SJason Gunthorpe
267ee190ab7SJason Gunthorpe ppriv = ipoib_priv(pdev);
268ee190ab7SJason Gunthorpe
269ee190ab7SJason Gunthorpe rc = -ENODEV;
270ee190ab7SJason Gunthorpe list_for_each_entry_safe(priv, tpriv, &ppriv->child_intfs, list) {
271ee190ab7SJason Gunthorpe if (priv->pkey == pkey &&
272ee190ab7SJason Gunthorpe priv->child_type == IPOIB_LEGACY_CHILD) {
273ee190ab7SJason Gunthorpe struct ipoib_vlan_delete_work *work;
274ee190ab7SJason Gunthorpe
275ee190ab7SJason Gunthorpe work = kmalloc(sizeof(*work), GFP_KERNEL);
276ee190ab7SJason Gunthorpe if (!work) {
277ee190ab7SJason Gunthorpe rc = -ENOMEM;
278ee190ab7SJason Gunthorpe goto out;
279ee190ab7SJason Gunthorpe }
280ee190ab7SJason Gunthorpe
281ee190ab7SJason Gunthorpe down_write(&ppriv->vlan_rwsem);
282ee190ab7SJason Gunthorpe list_del_init(&priv->list);
283ee190ab7SJason Gunthorpe up_write(&ppriv->vlan_rwsem);
284ee190ab7SJason Gunthorpe work->dev = priv->dev;
285ee190ab7SJason Gunthorpe INIT_WORK(&work->work, ipoib_vlan_delete_task);
286ee190ab7SJason Gunthorpe queue_work(ipoib_workqueue, &work->work);
287ee190ab7SJason Gunthorpe
288ee190ab7SJason Gunthorpe rc = 0;
289ee190ab7SJason Gunthorpe break;
290ee190ab7SJason Gunthorpe }
291ee190ab7SJason Gunthorpe }
292ee190ab7SJason Gunthorpe
293ee190ab7SJason Gunthorpe out:
294ee190ab7SJason Gunthorpe rtnl_unlock();
295ee190ab7SJason Gunthorpe
296ee190ab7SJason Gunthorpe return rc;
2971da177e4SLinus Torvalds }
298