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