19fa25171SDennis Dalessandro /*
2fe314195SDennis Dalessandro  * Copyright(c) 2016 Intel Corporation.
39fa25171SDennis Dalessandro  *
49fa25171SDennis Dalessandro  * This file is provided under a dual BSD/GPLv2 license.  When using or
59fa25171SDennis Dalessandro  * redistributing this file, you may do so under either license.
69fa25171SDennis Dalessandro  *
79fa25171SDennis Dalessandro  * GPL LICENSE SUMMARY
89fa25171SDennis Dalessandro  *
99fa25171SDennis Dalessandro  * This program is free software; you can redistribute it and/or modify
109fa25171SDennis Dalessandro  * it under the terms of version 2 of the GNU General Public License as
119fa25171SDennis Dalessandro  * published by the Free Software Foundation.
129fa25171SDennis Dalessandro  *
139fa25171SDennis Dalessandro  * This program is distributed in the hope that it will be useful, but
149fa25171SDennis Dalessandro  * WITHOUT ANY WARRANTY; without even the implied warranty of
159fa25171SDennis Dalessandro  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
169fa25171SDennis Dalessandro  * General Public License for more details.
179fa25171SDennis Dalessandro  *
189fa25171SDennis Dalessandro  * BSD LICENSE
199fa25171SDennis Dalessandro  *
209fa25171SDennis Dalessandro  * Redistribution and use in source and binary forms, with or without
219fa25171SDennis Dalessandro  * modification, are permitted provided that the following conditions
229fa25171SDennis Dalessandro  * are met:
239fa25171SDennis Dalessandro  *
249fa25171SDennis Dalessandro  *  - Redistributions of source code must retain the above copyright
259fa25171SDennis Dalessandro  *    notice, this list of conditions and the following disclaimer.
269fa25171SDennis Dalessandro  *  - Redistributions in binary form must reproduce the above copyright
279fa25171SDennis Dalessandro  *    notice, this list of conditions and the following disclaimer in
289fa25171SDennis Dalessandro  *    the documentation and/or other materials provided with the
299fa25171SDennis Dalessandro  *    distribution.
309fa25171SDennis Dalessandro  *  - Neither the name of Intel Corporation nor the names of its
319fa25171SDennis Dalessandro  *    contributors may be used to endorse or promote products derived
329fa25171SDennis Dalessandro  *    from this software without specific prior written permission.
339fa25171SDennis Dalessandro  *
349fa25171SDennis Dalessandro  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
359fa25171SDennis Dalessandro  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
369fa25171SDennis Dalessandro  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
379fa25171SDennis Dalessandro  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
389fa25171SDennis Dalessandro  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
399fa25171SDennis Dalessandro  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
409fa25171SDennis Dalessandro  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
419fa25171SDennis Dalessandro  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
429fa25171SDennis Dalessandro  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
439fa25171SDennis Dalessandro  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
449fa25171SDennis Dalessandro  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
459fa25171SDennis Dalessandro  *
469fa25171SDennis Dalessandro  */
479fa25171SDennis Dalessandro 
484e74080bSDennis Dalessandro #include <linux/slab.h>
494e74080bSDennis Dalessandro #include <linux/sched.h>
504e74080bSDennis Dalessandro #include <linux/rculist.h>
514e74080bSDennis Dalessandro #include <rdma/rdma_vt.h>
524e74080bSDennis Dalessandro #include <rdma/rdmavt_qp.h>
534e74080bSDennis Dalessandro 
549fa25171SDennis Dalessandro #include "mcast.h"
559fa25171SDennis Dalessandro 
564e74080bSDennis Dalessandro void rvt_driver_mcast_init(struct rvt_dev_info *rdi)
574e74080bSDennis Dalessandro {
584e74080bSDennis Dalessandro 	/*
594e74080bSDennis Dalessandro 	 * Anything that needs setup for multicast on a per driver or per rdi
604e74080bSDennis Dalessandro 	 * basis should be done in here.
614e74080bSDennis Dalessandro 	 */
624e74080bSDennis Dalessandro 	spin_lock_init(&rdi->n_mcast_grps_lock);
634e74080bSDennis Dalessandro }
644e74080bSDennis Dalessandro 
654e74080bSDennis Dalessandro /**
664e74080bSDennis Dalessandro  * mcast_qp_alloc - alloc a struct to link a QP to mcast GID struct
674e74080bSDennis Dalessandro  * @qp: the QP to link
684e74080bSDennis Dalessandro  */
694e74080bSDennis Dalessandro static struct rvt_mcast_qp *rvt_mcast_qp_alloc(struct rvt_qp *qp)
704e74080bSDennis Dalessandro {
714e74080bSDennis Dalessandro 	struct rvt_mcast_qp *mqp;
724e74080bSDennis Dalessandro 
734e74080bSDennis Dalessandro 	mqp = kmalloc(sizeof(*mqp), GFP_KERNEL);
744e74080bSDennis Dalessandro 	if (!mqp)
754e74080bSDennis Dalessandro 		goto bail;
764e74080bSDennis Dalessandro 
774e74080bSDennis Dalessandro 	mqp->qp = qp;
784e74080bSDennis Dalessandro 	atomic_inc(&qp->refcount);
794e74080bSDennis Dalessandro 
804e74080bSDennis Dalessandro bail:
814e74080bSDennis Dalessandro 	return mqp;
824e74080bSDennis Dalessandro }
834e74080bSDennis Dalessandro 
844e74080bSDennis Dalessandro static void rvt_mcast_qp_free(struct rvt_mcast_qp *mqp)
854e74080bSDennis Dalessandro {
864e74080bSDennis Dalessandro 	struct rvt_qp *qp = mqp->qp;
874e74080bSDennis Dalessandro 
884e74080bSDennis Dalessandro 	/* Notify hfi1_destroy_qp() if it is waiting. */
894e74080bSDennis Dalessandro 	if (atomic_dec_and_test(&qp->refcount))
904e74080bSDennis Dalessandro 		wake_up(&qp->wait);
914e74080bSDennis Dalessandro 
924e74080bSDennis Dalessandro 	kfree(mqp);
934e74080bSDennis Dalessandro }
944e74080bSDennis Dalessandro 
954e74080bSDennis Dalessandro /**
964e74080bSDennis Dalessandro  * mcast_alloc - allocate the multicast GID structure
974e74080bSDennis Dalessandro  * @mgid: the multicast GID
984e74080bSDennis Dalessandro  *
994e74080bSDennis Dalessandro  * A list of QPs will be attached to this structure.
1004e74080bSDennis Dalessandro  */
1014e74080bSDennis Dalessandro static struct rvt_mcast *rvt_mcast_alloc(union ib_gid *mgid)
1024e74080bSDennis Dalessandro {
1034e74080bSDennis Dalessandro 	struct rvt_mcast *mcast;
1044e74080bSDennis Dalessandro 
1054e74080bSDennis Dalessandro 	mcast = kzalloc(sizeof(*mcast), GFP_KERNEL);
1064e74080bSDennis Dalessandro 	if (!mcast)
1074e74080bSDennis Dalessandro 		goto bail;
1084e74080bSDennis Dalessandro 
1094e74080bSDennis Dalessandro 	mcast->mgid = *mgid;
1104e74080bSDennis Dalessandro 	INIT_LIST_HEAD(&mcast->qp_list);
1114e74080bSDennis Dalessandro 	init_waitqueue_head(&mcast->wait);
1124e74080bSDennis Dalessandro 	atomic_set(&mcast->refcount, 0);
1134e74080bSDennis Dalessandro 
1144e74080bSDennis Dalessandro bail:
1154e74080bSDennis Dalessandro 	return mcast;
1164e74080bSDennis Dalessandro }
1174e74080bSDennis Dalessandro 
1184e74080bSDennis Dalessandro static void rvt_mcast_free(struct rvt_mcast *mcast)
1194e74080bSDennis Dalessandro {
1204e74080bSDennis Dalessandro 	struct rvt_mcast_qp *p, *tmp;
1214e74080bSDennis Dalessandro 
1224e74080bSDennis Dalessandro 	list_for_each_entry_safe(p, tmp, &mcast->qp_list, list)
1234e74080bSDennis Dalessandro 		rvt_mcast_qp_free(p);
1244e74080bSDennis Dalessandro 
1254e74080bSDennis Dalessandro 	kfree(mcast);
1264e74080bSDennis Dalessandro }
1274e74080bSDennis Dalessandro 
1284e74080bSDennis Dalessandro /**
1294e74080bSDennis Dalessandro  * rvt_mcast_find - search the global table for the given multicast GID
1304e74080bSDennis Dalessandro  * @ibp: the IB port structure
1314e74080bSDennis Dalessandro  * @mgid: the multicast GID to search for
1324e74080bSDennis Dalessandro  *
1334e74080bSDennis Dalessandro  * Returns NULL if not found.
1344e74080bSDennis Dalessandro  *
1354e74080bSDennis Dalessandro  * The caller is responsible for decrementing the reference count if found.
1364e74080bSDennis Dalessandro  */
1374e74080bSDennis Dalessandro struct rvt_mcast *rvt_mcast_find(struct rvt_ibport *ibp, union ib_gid *mgid)
1384e74080bSDennis Dalessandro {
1394e74080bSDennis Dalessandro 	struct rb_node *n;
1404e74080bSDennis Dalessandro 	unsigned long flags;
1414e74080bSDennis Dalessandro 	struct rvt_mcast *found = NULL;
1424e74080bSDennis Dalessandro 
1434e74080bSDennis Dalessandro 	spin_lock_irqsave(&ibp->lock, flags);
1444e74080bSDennis Dalessandro 	n = ibp->mcast_tree.rb_node;
1454e74080bSDennis Dalessandro 	while (n) {
1464e74080bSDennis Dalessandro 		int ret;
1474e74080bSDennis Dalessandro 		struct rvt_mcast *mcast;
1484e74080bSDennis Dalessandro 
1494e74080bSDennis Dalessandro 		mcast = rb_entry(n, struct rvt_mcast, rb_node);
1504e74080bSDennis Dalessandro 
1514e74080bSDennis Dalessandro 		ret = memcmp(mgid->raw, mcast->mgid.raw,
1524e74080bSDennis Dalessandro 			     sizeof(union ib_gid));
1534e74080bSDennis Dalessandro 		if (ret < 0) {
1544e74080bSDennis Dalessandro 			n = n->rb_left;
1554e74080bSDennis Dalessandro 		} else if (ret > 0) {
1564e74080bSDennis Dalessandro 			n = n->rb_right;
1574e74080bSDennis Dalessandro 		} else {
1584e74080bSDennis Dalessandro 			atomic_inc(&mcast->refcount);
1594e74080bSDennis Dalessandro 			found = mcast;
1604e74080bSDennis Dalessandro 			break;
1614e74080bSDennis Dalessandro 		}
1624e74080bSDennis Dalessandro 	}
1634e74080bSDennis Dalessandro 	spin_unlock_irqrestore(&ibp->lock, flags);
1644e74080bSDennis Dalessandro 	return found;
1654e74080bSDennis Dalessandro }
1664e74080bSDennis Dalessandro EXPORT_SYMBOL(rvt_mcast_find);
1674e74080bSDennis Dalessandro 
1684e74080bSDennis Dalessandro /**
1694e74080bSDennis Dalessandro  * mcast_add - insert mcast GID into table and attach QP struct
1704e74080bSDennis Dalessandro  * @mcast: the mcast GID table
1714e74080bSDennis Dalessandro  * @mqp: the QP to attach
1724e74080bSDennis Dalessandro  *
1734e74080bSDennis Dalessandro  * Return zero if both were added.  Return EEXIST if the GID was already in
1744e74080bSDennis Dalessandro  * the table but the QP was added.  Return ESRCH if the QP was already
1754e74080bSDennis Dalessandro  * attached and neither structure was added.
1764e74080bSDennis Dalessandro  */
1774e74080bSDennis Dalessandro static int rvt_mcast_add(struct rvt_dev_info *rdi, struct rvt_ibport *ibp,
1784e74080bSDennis Dalessandro 			 struct rvt_mcast *mcast, struct rvt_mcast_qp *mqp)
1794e74080bSDennis Dalessandro {
1804e74080bSDennis Dalessandro 	struct rb_node **n = &ibp->mcast_tree.rb_node;
1814e74080bSDennis Dalessandro 	struct rb_node *pn = NULL;
1824e74080bSDennis Dalessandro 	int ret;
1834e74080bSDennis Dalessandro 
1844e74080bSDennis Dalessandro 	spin_lock_irq(&ibp->lock);
1854e74080bSDennis Dalessandro 
1864e74080bSDennis Dalessandro 	while (*n) {
1874e74080bSDennis Dalessandro 		struct rvt_mcast *tmcast;
1884e74080bSDennis Dalessandro 		struct rvt_mcast_qp *p;
1894e74080bSDennis Dalessandro 
1904e74080bSDennis Dalessandro 		pn = *n;
1914e74080bSDennis Dalessandro 		tmcast = rb_entry(pn, struct rvt_mcast, rb_node);
1924e74080bSDennis Dalessandro 
1934e74080bSDennis Dalessandro 		ret = memcmp(mcast->mgid.raw, tmcast->mgid.raw,
1944e74080bSDennis Dalessandro 			     sizeof(union ib_gid));
1954e74080bSDennis Dalessandro 		if (ret < 0) {
1964e74080bSDennis Dalessandro 			n = &pn->rb_left;
1974e74080bSDennis Dalessandro 			continue;
1984e74080bSDennis Dalessandro 		}
1994e74080bSDennis Dalessandro 		if (ret > 0) {
2004e74080bSDennis Dalessandro 			n = &pn->rb_right;
2014e74080bSDennis Dalessandro 			continue;
2024e74080bSDennis Dalessandro 		}
2034e74080bSDennis Dalessandro 
2044e74080bSDennis Dalessandro 		/* Search the QP list to see if this is already there. */
2054e74080bSDennis Dalessandro 		list_for_each_entry_rcu(p, &tmcast->qp_list, list) {
2064e74080bSDennis Dalessandro 			if (p->qp == mqp->qp) {
2074e74080bSDennis Dalessandro 				ret = ESRCH;
2084e74080bSDennis Dalessandro 				goto bail;
2094e74080bSDennis Dalessandro 			}
2104e74080bSDennis Dalessandro 		}
2114e74080bSDennis Dalessandro 		if (tmcast->n_attached ==
2124e74080bSDennis Dalessandro 		    rdi->dparms.props.max_mcast_qp_attach) {
2134e74080bSDennis Dalessandro 			ret = ENOMEM;
2144e74080bSDennis Dalessandro 			goto bail;
2154e74080bSDennis Dalessandro 		}
2164e74080bSDennis Dalessandro 
2174e74080bSDennis Dalessandro 		tmcast->n_attached++;
2184e74080bSDennis Dalessandro 
2194e74080bSDennis Dalessandro 		list_add_tail_rcu(&mqp->list, &tmcast->qp_list);
2204e74080bSDennis Dalessandro 		ret = EEXIST;
2214e74080bSDennis Dalessandro 		goto bail;
2224e74080bSDennis Dalessandro 	}
2234e74080bSDennis Dalessandro 
2244e74080bSDennis Dalessandro 	spin_lock(&rdi->n_mcast_grps_lock);
2254e74080bSDennis Dalessandro 	if (rdi->n_mcast_grps_allocated == rdi->dparms.props.max_mcast_grp) {
2264e74080bSDennis Dalessandro 		spin_unlock(&rdi->n_mcast_grps_lock);
2274e74080bSDennis Dalessandro 		ret = ENOMEM;
2284e74080bSDennis Dalessandro 		goto bail;
2294e74080bSDennis Dalessandro 	}
2304e74080bSDennis Dalessandro 
2314e74080bSDennis Dalessandro 	rdi->n_mcast_grps_allocated++;
2324e74080bSDennis Dalessandro 	spin_unlock(&rdi->n_mcast_grps_lock);
2334e74080bSDennis Dalessandro 
2344e74080bSDennis Dalessandro 	mcast->n_attached++;
2354e74080bSDennis Dalessandro 
2364e74080bSDennis Dalessandro 	list_add_tail_rcu(&mqp->list, &mcast->qp_list);
2374e74080bSDennis Dalessandro 
2384e74080bSDennis Dalessandro 	atomic_inc(&mcast->refcount);
2394e74080bSDennis Dalessandro 	rb_link_node(&mcast->rb_node, pn, n);
2404e74080bSDennis Dalessandro 	rb_insert_color(&mcast->rb_node, &ibp->mcast_tree);
2414e74080bSDennis Dalessandro 
2424e74080bSDennis Dalessandro 	ret = 0;
2434e74080bSDennis Dalessandro 
2444e74080bSDennis Dalessandro bail:
2454e74080bSDennis Dalessandro 	spin_unlock_irq(&ibp->lock);
2464e74080bSDennis Dalessandro 
2474e74080bSDennis Dalessandro 	return ret;
2484e74080bSDennis Dalessandro }
2494e74080bSDennis Dalessandro 
2509fa25171SDennis Dalessandro int rvt_attach_mcast(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
2519fa25171SDennis Dalessandro {
2524e74080bSDennis Dalessandro 	struct rvt_qp *qp = ibqp_to_rvtqp(ibqp);
2534e74080bSDennis Dalessandro 	struct rvt_dev_info *rdi = ib_to_rvt(ibqp->device);
2544e74080bSDennis Dalessandro 	struct rvt_ibport *ibp = rdi->ports[qp->port_num - 1];
2554e74080bSDennis Dalessandro 	struct rvt_mcast *mcast;
2564e74080bSDennis Dalessandro 	struct rvt_mcast_qp *mqp;
2574e74080bSDennis Dalessandro 	int ret = -ENOMEM;
2584e74080bSDennis Dalessandro 
2594e74080bSDennis Dalessandro 	if (ibqp->qp_num <= 1 || qp->state == IB_QPS_RESET)
2604e74080bSDennis Dalessandro 		return -EINVAL;
2614e74080bSDennis Dalessandro 
2624e74080bSDennis Dalessandro 	/*
2634e74080bSDennis Dalessandro 	 * Allocate data structures since its better to do this outside of
2644e74080bSDennis Dalessandro 	 * spin locks and it will most likely be needed.
2654e74080bSDennis Dalessandro 	 */
2664e74080bSDennis Dalessandro 	mcast = rvt_mcast_alloc(gid);
2674e74080bSDennis Dalessandro 	if (!mcast)
2684e74080bSDennis Dalessandro 		return -ENOMEM;
2694e74080bSDennis Dalessandro 
2704e74080bSDennis Dalessandro 	mqp = rvt_mcast_qp_alloc(qp);
2714e74080bSDennis Dalessandro 	if (!mqp)
2724e74080bSDennis Dalessandro 		goto bail_mcast;
2734e74080bSDennis Dalessandro 
2744e74080bSDennis Dalessandro 	switch (rvt_mcast_add(rdi, ibp, mcast, mqp)) {
2754e74080bSDennis Dalessandro 	case ESRCH:
2764e74080bSDennis Dalessandro 		/* Neither was used: OK to attach the same QP twice. */
2774e74080bSDennis Dalessandro 		ret = 0;
2784e74080bSDennis Dalessandro 		goto bail_mqp;
2794e74080bSDennis Dalessandro 	case EEXIST: /* The mcast wasn't used */
2804e74080bSDennis Dalessandro 		ret = 0;
2814e74080bSDennis Dalessandro 		goto bail_mcast;
2824e74080bSDennis Dalessandro 	case ENOMEM:
2834e74080bSDennis Dalessandro 		/* Exceeded the maximum number of mcast groups. */
2844e74080bSDennis Dalessandro 		ret = -ENOMEM;
2854e74080bSDennis Dalessandro 		goto bail_mqp;
2864e74080bSDennis Dalessandro 	default:
2874e74080bSDennis Dalessandro 		break;
2884e74080bSDennis Dalessandro 	}
2894e74080bSDennis Dalessandro 
2904e74080bSDennis Dalessandro 	return 0;
2914e74080bSDennis Dalessandro 
2924e74080bSDennis Dalessandro bail_mqp:
2934e74080bSDennis Dalessandro 	rvt_mcast_qp_free(mqp);
2944e74080bSDennis Dalessandro 
2954e74080bSDennis Dalessandro bail_mcast:
2964e74080bSDennis Dalessandro 	rvt_mcast_free(mcast);
2974e74080bSDennis Dalessandro 
2984e74080bSDennis Dalessandro 	return ret;
2999fa25171SDennis Dalessandro }
3009fa25171SDennis Dalessandro 
3019fa25171SDennis Dalessandro int rvt_detach_mcast(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
3029fa25171SDennis Dalessandro {
3034e74080bSDennis Dalessandro 	struct rvt_qp *qp = ibqp_to_rvtqp(ibqp);
3044e74080bSDennis Dalessandro 	struct rvt_dev_info *rdi = ib_to_rvt(ibqp->device);
3054e74080bSDennis Dalessandro 	struct rvt_ibport *ibp = rdi->ports[qp->port_num - 1];
3064e74080bSDennis Dalessandro 	struct rvt_mcast *mcast = NULL;
3074e74080bSDennis Dalessandro 	struct rvt_mcast_qp *p, *tmp, *delp = NULL;
3084e74080bSDennis Dalessandro 	struct rb_node *n;
3094e74080bSDennis Dalessandro 	int last = 0;
3104e74080bSDennis Dalessandro 	int ret = 0;
3114e74080bSDennis Dalessandro 
3124e74080bSDennis Dalessandro 	if (ibqp->qp_num <= 1 || qp->state == IB_QPS_RESET)
3134e74080bSDennis Dalessandro 		return -EINVAL;
3144e74080bSDennis Dalessandro 
3154e74080bSDennis Dalessandro 	spin_lock_irq(&ibp->lock);
3164e74080bSDennis Dalessandro 
3174e74080bSDennis Dalessandro 	/* Find the GID in the mcast table. */
3184e74080bSDennis Dalessandro 	n = ibp->mcast_tree.rb_node;
3194e74080bSDennis Dalessandro 	while (1) {
3204e74080bSDennis Dalessandro 		if (!n) {
3214e74080bSDennis Dalessandro 			spin_unlock_irq(&ibp->lock);
3224e74080bSDennis Dalessandro 			return -EINVAL;
3234e74080bSDennis Dalessandro 		}
3244e74080bSDennis Dalessandro 
3254e74080bSDennis Dalessandro 		mcast = rb_entry(n, struct rvt_mcast, rb_node);
3264e74080bSDennis Dalessandro 		ret = memcmp(gid->raw, mcast->mgid.raw,
3274e74080bSDennis Dalessandro 			     sizeof(union ib_gid));
3284e74080bSDennis Dalessandro 		if (ret < 0)
3294e74080bSDennis Dalessandro 			n = n->rb_left;
3304e74080bSDennis Dalessandro 		else if (ret > 0)
3314e74080bSDennis Dalessandro 			n = n->rb_right;
3324e74080bSDennis Dalessandro 		else
3334e74080bSDennis Dalessandro 			break;
3344e74080bSDennis Dalessandro 	}
3354e74080bSDennis Dalessandro 
3364e74080bSDennis Dalessandro 	/* Search the QP list. */
3374e74080bSDennis Dalessandro 	list_for_each_entry_safe(p, tmp, &mcast->qp_list, list) {
3384e74080bSDennis Dalessandro 		if (p->qp != qp)
3394e74080bSDennis Dalessandro 			continue;
3404e74080bSDennis Dalessandro 		/*
3414e74080bSDennis Dalessandro 		 * We found it, so remove it, but don't poison the forward
3424e74080bSDennis Dalessandro 		 * link until we are sure there are no list walkers.
3434e74080bSDennis Dalessandro 		 */
3444e74080bSDennis Dalessandro 		list_del_rcu(&p->list);
3454e74080bSDennis Dalessandro 		mcast->n_attached--;
3464e74080bSDennis Dalessandro 		delp = p;
3474e74080bSDennis Dalessandro 
3484e74080bSDennis Dalessandro 		/* If this was the last attached QP, remove the GID too. */
3494e74080bSDennis Dalessandro 		if (list_empty(&mcast->qp_list)) {
3504e74080bSDennis Dalessandro 			rb_erase(&mcast->rb_node, &ibp->mcast_tree);
3514e74080bSDennis Dalessandro 			last = 1;
3524e74080bSDennis Dalessandro 		}
3534e74080bSDennis Dalessandro 		break;
3544e74080bSDennis Dalessandro 	}
3554e74080bSDennis Dalessandro 
3564e74080bSDennis Dalessandro 	spin_unlock_irq(&ibp->lock);
3574e74080bSDennis Dalessandro 	/* QP not attached */
3584e74080bSDennis Dalessandro 	if (!delp)
3594e74080bSDennis Dalessandro 		return -EINVAL;
3604e74080bSDennis Dalessandro 
3614e74080bSDennis Dalessandro 	/*
3624e74080bSDennis Dalessandro 	 * Wait for any list walkers to finish before freeing the
3634e74080bSDennis Dalessandro 	 * list element.
3644e74080bSDennis Dalessandro 	 */
3654e74080bSDennis Dalessandro 	wait_event(mcast->wait, atomic_read(&mcast->refcount) <= 1);
3664e74080bSDennis Dalessandro 	rvt_mcast_qp_free(delp);
3674e74080bSDennis Dalessandro 
3684e74080bSDennis Dalessandro 	if (last) {
3694e74080bSDennis Dalessandro 		atomic_dec(&mcast->refcount);
3704e74080bSDennis Dalessandro 		wait_event(mcast->wait, !atomic_read(&mcast->refcount));
3714e74080bSDennis Dalessandro 		rvt_mcast_free(mcast);
3724e74080bSDennis Dalessandro 		spin_lock_irq(&rdi->n_mcast_grps_lock);
3734e74080bSDennis Dalessandro 		rdi->n_mcast_grps_allocated--;
3744e74080bSDennis Dalessandro 		spin_unlock_irq(&rdi->n_mcast_grps_lock);
3754e74080bSDennis Dalessandro 	}
3764e74080bSDennis Dalessandro 
3774e74080bSDennis Dalessandro 	return 0;
3784e74080bSDennis Dalessandro }
3794e74080bSDennis Dalessandro 
3804e74080bSDennis Dalessandro int rvt_mcast_tree_empty(struct rvt_dev_info *rdi)
3814e74080bSDennis Dalessandro {
3824e74080bSDennis Dalessandro 	int i;
3834e74080bSDennis Dalessandro 	int in_use = 0;
3844e74080bSDennis Dalessandro 
3854e74080bSDennis Dalessandro 	for (i = 0; i < rdi->dparms.nports; i++)
3864e74080bSDennis Dalessandro 		if (rdi->ports[i]->mcast_tree.rb_node)
3874e74080bSDennis Dalessandro 			in_use++;
3884e74080bSDennis Dalessandro 	return in_use;
3899fa25171SDennis Dalessandro }
390