1 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
3 * Copyright (c) 2016 Mellanox Technologies Ltd. All rights reserved.
4 * Copyright (c) 2015 System Fabric Works, Inc. All rights reserved.
10 /* caller should hold mc_grp_pool->pool_lock */
11 static struct rxe_mc_grp *create_grp(struct rxe_dev *rxe,
12 struct rxe_pool *pool,
16 struct rxe_mc_grp *grp;
18 grp = rxe_alloc_locked(&rxe->mc_grp_pool);
20 return ERR_PTR(-ENOMEM);
22 INIT_LIST_HEAD(&grp->qp_list);
23 spin_lock_init(&grp->mcg_lock);
25 rxe_add_key_locked(grp, mgid);
27 err = rxe_mcast_add(rxe, mgid);
29 rxe_drop_key_locked(grp);
37 int rxe_mcast_get_grp(struct rxe_dev *rxe, union ib_gid *mgid,
38 struct rxe_mc_grp **grp_p)
41 struct rxe_mc_grp *grp;
42 struct rxe_pool *pool = &rxe->mc_grp_pool;
45 if (rxe->attr.max_mcast_qp_attach == 0)
48 write_lock_irqsave(&pool->pool_lock, flags);
50 grp = rxe_pool_get_key_locked(pool, mgid);
54 grp = create_grp(rxe, pool, mgid);
56 write_unlock_irqrestore(&pool->pool_lock, flags);
62 write_unlock_irqrestore(&pool->pool_lock, flags);
67 int rxe_mcast_add_grp_elem(struct rxe_dev *rxe, struct rxe_qp *qp,
68 struct rxe_mc_grp *grp)
71 struct rxe_mc_elem *elem;
73 /* check to see of the qp is already a member of the group */
74 spin_lock_bh(&qp->grp_lock);
75 spin_lock_bh(&grp->mcg_lock);
76 list_for_each_entry(elem, &grp->qp_list, qp_list) {
83 if (grp->num_qp >= rxe->attr.max_mcast_qp_attach) {
88 elem = rxe_alloc(&rxe->mc_elem_pool);
94 /* each qp holds a ref on the grp */
101 list_add(&elem->qp_list, &grp->qp_list);
102 list_add(&elem->grp_list, &qp->grp_list);
106 spin_unlock_bh(&grp->mcg_lock);
107 spin_unlock_bh(&qp->grp_lock);
111 int rxe_mcast_drop_grp_elem(struct rxe_dev *rxe, struct rxe_qp *qp,
114 struct rxe_mc_grp *grp;
115 struct rxe_mc_elem *elem, *tmp;
117 grp = rxe_pool_get_key(&rxe->mc_grp_pool, mgid);
121 spin_lock_bh(&qp->grp_lock);
122 spin_lock_bh(&grp->mcg_lock);
124 list_for_each_entry_safe(elem, tmp, &grp->qp_list, qp_list) {
125 if (elem->qp == qp) {
126 list_del(&elem->qp_list);
127 list_del(&elem->grp_list);
130 spin_unlock_bh(&grp->mcg_lock);
131 spin_unlock_bh(&qp->grp_lock);
133 rxe_drop_ref(grp); /* ref held by QP */
134 rxe_drop_ref(grp); /* ref from get_key */
139 spin_unlock_bh(&grp->mcg_lock);
140 spin_unlock_bh(&qp->grp_lock);
141 rxe_drop_ref(grp); /* ref from get_key */
146 void rxe_drop_all_mcast_groups(struct rxe_qp *qp)
148 struct rxe_mc_grp *grp;
149 struct rxe_mc_elem *elem;
152 spin_lock_bh(&qp->grp_lock);
153 if (list_empty(&qp->grp_list)) {
154 spin_unlock_bh(&qp->grp_lock);
157 elem = list_first_entry(&qp->grp_list, struct rxe_mc_elem,
159 list_del(&elem->grp_list);
160 spin_unlock_bh(&qp->grp_lock);
163 spin_lock_bh(&grp->mcg_lock);
164 list_del(&elem->qp_list);
166 spin_unlock_bh(&grp->mcg_lock);
172 void rxe_mc_cleanup(struct rxe_pool_entry *arg)
174 struct rxe_mc_grp *grp = container_of(arg, typeof(*grp), pelem);
175 struct rxe_dev *rxe = grp->rxe;
178 rxe_mcast_delete(rxe, &grp->mgid);