diff options
Diffstat (limited to 'drivers/infiniband/hw/qib/qib_verbs_mcast.c')
-rw-r--r-- | drivers/infiniband/hw/qib/qib_verbs_mcast.c | 35 |
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 | |||
361 | bail: | ||
362 | return ret; | ||
363 | } | 358 | } |
364 | 359 | ||
365 | int qib_mcast_tree_empty(struct qib_ibport *ibp) | 360 | int qib_mcast_tree_empty(struct qib_ibport *ibp) |