1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause 2 /* 3 * Copyright(c) 2016 Intel Corporation. 4 */ 5 6 #include <linux/slab.h> 7 #include <linux/sched.h> 8 #include <linux/rculist.h> 9 #include <rdma/rdma_vt.h> 10 #include <rdma/rdmavt_qp.h> 11 12 #include "mcast.h" 13 14 /** 15 * rvt_driver_mcast_init - init resources for multicast 16 * @rdi: rvt dev struct 17 * 18 * This is per device that registers with rdmavt 19 */ 20 void rvt_driver_mcast_init(struct rvt_dev_info *rdi) 21 { 22 /* 23 * Anything that needs setup for multicast on a per driver or per rdi 24 * basis should be done in here. 25 */ 26 spin_lock_init(&rdi->n_mcast_grps_lock); 27 } 28 29 /** 30 * rvt_mcast_qp_alloc - alloc a struct to link a QP to mcast GID struct 31 * @qp: the QP to link 32 */ 33 static struct rvt_mcast_qp *rvt_mcast_qp_alloc(struct rvt_qp *qp) 34 { 35 struct rvt_mcast_qp *mqp; 36 37 mqp = kmalloc_obj(*mqp); 38 if (!mqp) 39 goto bail; 40 41 mqp->qp = qp; 42 rvt_get_qp(qp); 43 44 bail: 45 return mqp; 46 } 47 48 static void rvt_mcast_qp_free(struct rvt_mcast_qp *mqp) 49 { 50 struct rvt_qp *qp = mqp->qp; 51 52 rvt_put_qp(qp); 53 54 kfree(mqp); 55 } 56 57 /** 58 * rvt_mcast_alloc - allocate the multicast GID structure 59 * @mgid: the multicast GID 60 * @lid: the muilticast LID (host order) 61 * 62 * A list of QPs will be attached to this structure. 63 */ 64 static struct rvt_mcast *rvt_mcast_alloc(union ib_gid *mgid, u16 lid) 65 { 66 struct rvt_mcast *mcast; 67 68 mcast = kzalloc_obj(*mcast); 69 if (!mcast) 70 goto bail; 71 72 mcast->mcast_addr.mgid = *mgid; 73 mcast->mcast_addr.lid = lid; 74 75 INIT_LIST_HEAD(&mcast->qp_list); 76 init_waitqueue_head(&mcast->wait); 77 atomic_set(&mcast->refcount, 0); 78 79 bail: 80 return mcast; 81 } 82 83 static void rvt_mcast_free(struct rvt_mcast *mcast) 84 { 85 struct rvt_mcast_qp *p, *tmp; 86 87 list_for_each_entry_safe(p, tmp, &mcast->qp_list, list) 88 rvt_mcast_qp_free(p); 89 90 kfree(mcast); 91 } 92 93 /** 94 * rvt_mcast_find - search the global table for the given multicast GID/LID 95 * NOTE: It is valid to have 1 MLID with multiple MGIDs. It is not valid 96 * to have 1 MGID with multiple MLIDs. 97 * @ibp: the IB port structure 98 * @mgid: the multicast GID to search for 99 * @lid: the multicast LID portion of the multicast address (host order) 100 * 101 * The caller is responsible for decrementing the reference count if found. 102 * 103 * Return: NULL if not found. 104 */ 105 struct rvt_mcast *rvt_mcast_find(struct rvt_ibport *ibp, union ib_gid *mgid, 106 u16 lid) 107 { 108 struct rb_node *n; 109 unsigned long flags; 110 struct rvt_mcast *found = NULL; 111 112 spin_lock_irqsave(&ibp->lock, flags); 113 n = ibp->mcast_tree.rb_node; 114 while (n) { 115 int ret; 116 struct rvt_mcast *mcast; 117 118 mcast = rb_entry(n, struct rvt_mcast, rb_node); 119 120 ret = memcmp(mgid->raw, mcast->mcast_addr.mgid.raw, 121 sizeof(*mgid)); 122 if (ret < 0) { 123 n = n->rb_left; 124 } else if (ret > 0) { 125 n = n->rb_right; 126 } else { 127 /* MGID/MLID must match */ 128 if (mcast->mcast_addr.lid == lid) { 129 atomic_inc(&mcast->refcount); 130 found = mcast; 131 } 132 break; 133 } 134 } 135 spin_unlock_irqrestore(&ibp->lock, flags); 136 return found; 137 } 138 EXPORT_SYMBOL(rvt_mcast_find); 139 140 /* 141 * rvt_mcast_add - insert mcast GID into table and attach QP struct 142 * @mcast: the mcast GID table 143 * @mqp: the QP to attach 144 * 145 * Return: zero if both were added. Return EEXIST if the GID was already in 146 * the table but the QP was added. Return ESRCH if the QP was already 147 * attached and neither structure was added. Return EINVAL if the MGID was 148 * found, but the MLID did NOT match. 149 */ 150 static int rvt_mcast_add(struct rvt_dev_info *rdi, struct rvt_ibport *ibp, 151 struct rvt_mcast *mcast, struct rvt_mcast_qp *mqp) 152 { 153 struct rb_node **n = &ibp->mcast_tree.rb_node; 154 struct rb_node *pn = NULL; 155 int ret; 156 157 spin_lock_irq(&ibp->lock); 158 159 while (*n) { 160 struct rvt_mcast *tmcast; 161 struct rvt_mcast_qp *p; 162 163 pn = *n; 164 tmcast = rb_entry(pn, struct rvt_mcast, rb_node); 165 166 ret = memcmp(mcast->mcast_addr.mgid.raw, 167 tmcast->mcast_addr.mgid.raw, 168 sizeof(mcast->mcast_addr.mgid)); 169 if (ret < 0) { 170 n = &pn->rb_left; 171 continue; 172 } 173 if (ret > 0) { 174 n = &pn->rb_right; 175 continue; 176 } 177 178 if (tmcast->mcast_addr.lid != mcast->mcast_addr.lid) { 179 ret = EINVAL; 180 goto bail; 181 } 182 183 /* Search the QP list to see if this is already there. */ 184 list_for_each_entry_rcu(p, &tmcast->qp_list, list) { 185 if (p->qp == mqp->qp) { 186 ret = ESRCH; 187 goto bail; 188 } 189 } 190 if (tmcast->n_attached == 191 rdi->dparms.props.max_mcast_qp_attach) { 192 ret = ENOMEM; 193 goto bail; 194 } 195 196 tmcast->n_attached++; 197 198 list_add_tail_rcu(&mqp->list, &tmcast->qp_list); 199 ret = EEXIST; 200 goto bail; 201 } 202 203 spin_lock(&rdi->n_mcast_grps_lock); 204 if (rdi->n_mcast_grps_allocated == rdi->dparms.props.max_mcast_grp) { 205 spin_unlock(&rdi->n_mcast_grps_lock); 206 ret = ENOMEM; 207 goto bail; 208 } 209 210 rdi->n_mcast_grps_allocated++; 211 spin_unlock(&rdi->n_mcast_grps_lock); 212 213 mcast->n_attached++; 214 215 list_add_tail_rcu(&mqp->list, &mcast->qp_list); 216 217 atomic_inc(&mcast->refcount); 218 rb_link_node(&mcast->rb_node, pn, n); 219 rb_insert_color(&mcast->rb_node, &ibp->mcast_tree); 220 221 ret = 0; 222 223 bail: 224 spin_unlock_irq(&ibp->lock); 225 226 return ret; 227 } 228 229 /** 230 * rvt_attach_mcast - attach a qp to a multicast group 231 * @ibqp: Infiniband qp 232 * @gid: multicast guid 233 * @lid: multicast lid 234 * 235 * Return: 0 on success 236 */ 237 int rvt_attach_mcast(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) 238 { 239 struct rvt_qp *qp = ibqp_to_rvtqp(ibqp); 240 struct rvt_dev_info *rdi = ib_to_rvt(ibqp->device); 241 struct rvt_ibport *ibp = rdi->ports[qp->port_num - 1]; 242 struct rvt_mcast *mcast; 243 struct rvt_mcast_qp *mqp; 244 int ret = -ENOMEM; 245 246 if (ibqp->qp_num <= 1 || qp->state == IB_QPS_RESET) 247 return -EINVAL; 248 249 /* 250 * Allocate data structures since its better to do this outside of 251 * spin locks and it will most likely be needed. 252 */ 253 mcast = rvt_mcast_alloc(gid, lid); 254 if (!mcast) 255 return -ENOMEM; 256 257 mqp = rvt_mcast_qp_alloc(qp); 258 if (!mqp) 259 goto bail_mcast; 260 261 switch (rvt_mcast_add(rdi, ibp, mcast, mqp)) { 262 case ESRCH: 263 /* Neither was used: OK to attach the same QP twice. */ 264 ret = 0; 265 goto bail_mqp; 266 case EEXIST: /* The mcast wasn't used */ 267 ret = 0; 268 goto bail_mcast; 269 case ENOMEM: 270 /* Exceeded the maximum number of mcast groups. */ 271 ret = -ENOMEM; 272 goto bail_mqp; 273 case EINVAL: 274 /* Invalid MGID/MLID pair */ 275 ret = -EINVAL; 276 goto bail_mqp; 277 default: 278 break; 279 } 280 281 return 0; 282 283 bail_mqp: 284 rvt_mcast_qp_free(mqp); 285 286 bail_mcast: 287 rvt_mcast_free(mcast); 288 289 return ret; 290 } 291 292 /** 293 * rvt_detach_mcast - remove a qp from a multicast group 294 * @ibqp: Infiniband qp 295 * @gid: multicast guid 296 * @lid: multicast lid 297 * 298 * Return: 0 on success 299 */ 300 int rvt_detach_mcast(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) 301 { 302 struct rvt_qp *qp = ibqp_to_rvtqp(ibqp); 303 struct rvt_dev_info *rdi = ib_to_rvt(ibqp->device); 304 struct rvt_ibport *ibp = rdi->ports[qp->port_num - 1]; 305 struct rvt_mcast *mcast = NULL; 306 struct rvt_mcast_qp *p, *tmp, *delp = NULL; 307 struct rb_node *n; 308 int last = 0; 309 int ret = 0; 310 311 if (ibqp->qp_num <= 1) 312 return -EINVAL; 313 314 spin_lock_irq(&ibp->lock); 315 316 /* Find the GID in the mcast table. */ 317 n = ibp->mcast_tree.rb_node; 318 while (1) { 319 if (!n) { 320 spin_unlock_irq(&ibp->lock); 321 return -EINVAL; 322 } 323 324 mcast = rb_entry(n, struct rvt_mcast, rb_node); 325 ret = memcmp(gid->raw, mcast->mcast_addr.mgid.raw, 326 sizeof(*gid)); 327 if (ret < 0) { 328 n = n->rb_left; 329 } else if (ret > 0) { 330 n = n->rb_right; 331 } else { 332 /* MGID/MLID must match */ 333 if (mcast->mcast_addr.lid != lid) { 334 spin_unlock_irq(&ibp->lock); 335 return -EINVAL; 336 } 337 break; 338 } 339 } 340 341 /* Search the QP list. */ 342 list_for_each_entry_safe(p, tmp, &mcast->qp_list, list) { 343 if (p->qp != qp) 344 continue; 345 /* 346 * We found it, so remove it, but don't poison the forward 347 * link until we are sure there are no list walkers. 348 */ 349 list_del_rcu(&p->list); 350 mcast->n_attached--; 351 delp = p; 352 353 /* If this was the last attached QP, remove the GID too. */ 354 if (list_empty(&mcast->qp_list)) { 355 rb_erase(&mcast->rb_node, &ibp->mcast_tree); 356 last = 1; 357 } 358 break; 359 } 360 361 spin_unlock_irq(&ibp->lock); 362 /* QP not attached */ 363 if (!delp) 364 return -EINVAL; 365 366 /* 367 * Wait for any list walkers to finish before freeing the 368 * list element. 369 */ 370 wait_event(mcast->wait, atomic_read(&mcast->refcount) <= 1); 371 rvt_mcast_qp_free(delp); 372 373 if (last) { 374 atomic_dec(&mcast->refcount); 375 wait_event(mcast->wait, !atomic_read(&mcast->refcount)); 376 rvt_mcast_free(mcast); 377 spin_lock_irq(&rdi->n_mcast_grps_lock); 378 rdi->n_mcast_grps_allocated--; 379 spin_unlock_irq(&rdi->n_mcast_grps_lock); 380 } 381 382 return 0; 383 } 384 385 /** 386 * rvt_mcast_tree_empty - determine if any qps are attached to any mcast group 387 * @rdi: rvt dev struct 388 * 389 * Return: in use count 390 */ 391 int rvt_mcast_tree_empty(struct rvt_dev_info *rdi) 392 { 393 int i; 394 int in_use = 0; 395 396 for (i = 0; i < rdi->dparms.nports; i++) 397 if (rdi->ports[i]->mcast_tree.rb_node) 398 in_use++; 399 return in_use; 400 } 401