aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/infiniband/hw/qib/qib_verbs_mcast.c')
-rw-r--r--drivers/infiniband/hw/qib/qib_verbs_mcast.c35
1 files changed, 15 insertions, 20 deletions
diff --git a/drivers/infiniband/hw/qib/qib_verbs_mcast.c b/drivers/infiniband/hw/qib/qib_verbs_mcast.c
index dabb697b1c2..48ba1c3e945 100644
--- a/drivers/infiniband/hw/qib/qib_verbs_mcast.c
+++ b/drivers/infiniband/hw/qib/qib_verbs_mcast.c
@@ -286,15 +286,13 @@ int qib_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
286 struct qib_ibdev *dev = to_idev(ibqp->device); 286 struct qib_ibdev *dev = to_idev(ibqp->device);
287 struct qib_ibport *ibp = to_iport(ibqp->device, qp->port_num); 287 struct qib_ibport *ibp = to_iport(ibqp->device, qp->port_num);
288 struct qib_mcast *mcast = NULL; 288 struct qib_mcast *mcast = NULL;
289 struct qib_mcast_qp *p, *tmp; 289 struct qib_mcast_qp *p, *tmp, *delp = NULL;
290 struct rb_node *n; 290 struct rb_node *n;
291 int last = 0; 291 int last = 0;
292 int ret; 292 int ret;
293 293
294 if (ibqp->qp_num <= 1 || qp->state == IB_QPS_RESET) { 294 if (ibqp->qp_num <= 1 || qp->state == IB_QPS_RESET)
295 ret = -EINVAL; 295 return -EINVAL;
296 goto bail;
297 }
298 296
299 spin_lock_irq(&ibp->lock); 297 spin_lock_irq(&ibp->lock);
300 298
@@ -303,8 +301,7 @@ int qib_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
303 while (1) { 301 while (1) {
304 if (n == NULL) { 302 if (n == NULL) {
305 spin_unlock_irq(&ibp->lock); 303 spin_unlock_irq(&ibp->lock);
306 ret = -EINVAL; 304 return -EINVAL;
307 goto bail;
308 } 305 }
309 306
310 mcast = rb_entry(n, struct qib_mcast, rb_node); 307 mcast = rb_entry(n, struct qib_mcast, rb_node);
@@ -328,6 +325,7 @@ int qib_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
328 */ 325 */
329 list_del_rcu(&p->list); 326 list_del_rcu(&p->list);
330 mcast->n_attached--; 327 mcast->n_attached--;
328 delp = p;
331 329
332 /* If this was the last attached QP, remove the GID too. */ 330 /* If this was the last attached QP, remove the GID too. */
333 if (list_empty(&mcast->qp_list)) { 331 if (list_empty(&mcast->qp_list)) {
@@ -338,15 +336,16 @@ int qib_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
338 } 336 }
339 337
340 spin_unlock_irq(&ibp->lock); 338 spin_unlock_irq(&ibp->lock);
339 /* QP not attached */
340 if (!delp)
341 return -EINVAL;
342 /*
343 * Wait for any list walkers to finish before freeing the
344 * list element.
345 */
346 wait_event(mcast->wait, atomic_read(&mcast->refcount) <= 1);
347 qib_mcast_qp_free(delp);
341 348
342 if (p) {
343 /*
344 * Wait for any list walkers to finish before freeing the
345 * list element.
346 */
347 wait_event(mcast->wait, atomic_read(&mcast->refcount) <= 1);
348 qib_mcast_qp_free(p);
349 }
350 if (last) { 349 if (last) {
351 atomic_dec(&mcast->refcount); 350 atomic_dec(&mcast->refcount);
352 wait_event(mcast->wait, !atomic_read(&mcast->refcount)); 351 wait_event(mcast->wait, !atomic_read(&mcast->refcount));
@@ -355,11 +354,7 @@ int qib_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
355 dev->n_mcast_grps_allocated--; 354 dev->n_mcast_grps_allocated--;
356 spin_unlock_irq(&dev->n_mcast_grps_lock); 355 spin_unlock_irq(&dev->n_mcast_grps_lock);
357 } 356 }
358 357 return 0;
359 ret = 0;
360
361bail:
362 return ret;
363} 358}
364 359
365int qib_mcast_tree_empty(struct qib_ibport *ibp) 360int qib_mcast_tree_empty(struct qib_ibport *ibp)