diff options
| -rw-r--r-- | drivers/infiniband/ulp/ipoib/ipoib_multicast.c | 24 |
1 files changed, 17 insertions, 7 deletions
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c index 050dfa175d16..25889311b1e9 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c | |||
| @@ -456,7 +456,10 @@ out_locked: | |||
| 456 | return status; | 456 | return status; |
| 457 | } | 457 | } |
| 458 | 458 | ||
| 459 | static void ipoib_mcast_join(struct net_device *dev, struct ipoib_mcast *mcast) | 459 | /* |
| 460 | * Caller must hold 'priv->lock' | ||
| 461 | */ | ||
| 462 | static int ipoib_mcast_join(struct net_device *dev, struct ipoib_mcast *mcast) | ||
| 460 | { | 463 | { |
| 461 | struct ipoib_dev_priv *priv = netdev_priv(dev); | 464 | struct ipoib_dev_priv *priv = netdev_priv(dev); |
| 462 | struct ib_sa_multicast *multicast; | 465 | struct ib_sa_multicast *multicast; |
| @@ -466,6 +469,10 @@ static void ipoib_mcast_join(struct net_device *dev, struct ipoib_mcast *mcast) | |||
| 466 | ib_sa_comp_mask comp_mask; | 469 | ib_sa_comp_mask comp_mask; |
| 467 | int ret = 0; | 470 | int ret = 0; |
| 468 | 471 | ||
| 472 | if (!priv->broadcast || | ||
| 473 | !test_bit(IPOIB_FLAG_OPER_UP, &priv->flags)) | ||
| 474 | return -EINVAL; | ||
| 475 | |||
| 469 | ipoib_dbg_mcast(priv, "joining MGID %pI6\n", mcast->mcmember.mgid.raw); | 476 | ipoib_dbg_mcast(priv, "joining MGID %pI6\n", mcast->mcmember.mgid.raw); |
| 470 | 477 | ||
| 471 | rec.mgid = mcast->mcmember.mgid; | 478 | rec.mgid = mcast->mcmember.mgid; |
| @@ -525,20 +532,23 @@ static void ipoib_mcast_join(struct net_device *dev, struct ipoib_mcast *mcast) | |||
| 525 | rec.join_state = 4; | 532 | rec.join_state = 4; |
| 526 | #endif | 533 | #endif |
| 527 | } | 534 | } |
| 535 | spin_unlock_irq(&priv->lock); | ||
| 528 | 536 | ||
| 529 | multicast = ib_sa_join_multicast(&ipoib_sa_client, priv->ca, priv->port, | 537 | multicast = ib_sa_join_multicast(&ipoib_sa_client, priv->ca, priv->port, |
| 530 | &rec, comp_mask, GFP_KERNEL, | 538 | &rec, comp_mask, GFP_KERNEL, |
| 531 | ipoib_mcast_join_complete, mcast); | 539 | ipoib_mcast_join_complete, mcast); |
| 540 | spin_lock_irq(&priv->lock); | ||
| 532 | if (IS_ERR(multicast)) { | 541 | if (IS_ERR(multicast)) { |
| 533 | ret = PTR_ERR(multicast); | 542 | ret = PTR_ERR(multicast); |
| 534 | ipoib_warn(priv, "ib_sa_join_multicast failed, status %d\n", ret); | 543 | ipoib_warn(priv, "ib_sa_join_multicast failed, status %d\n", ret); |
| 535 | spin_lock_irq(&priv->lock); | ||
| 536 | /* Requeue this join task with a backoff delay */ | 544 | /* Requeue this join task with a backoff delay */ |
| 537 | __ipoib_mcast_schedule_join_thread(priv, mcast, 1); | 545 | __ipoib_mcast_schedule_join_thread(priv, mcast, 1); |
| 538 | clear_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags); | 546 | clear_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags); |
| 539 | spin_unlock_irq(&priv->lock); | 547 | spin_unlock_irq(&priv->lock); |
| 540 | complete(&mcast->done); | 548 | complete(&mcast->done); |
| 549 | spin_lock_irq(&priv->lock); | ||
| 541 | } | 550 | } |
| 551 | return 0; | ||
| 542 | } | 552 | } |
| 543 | 553 | ||
| 544 | void ipoib_mcast_join_task(struct work_struct *work) | 554 | void ipoib_mcast_join_task(struct work_struct *work) |
| @@ -620,9 +630,10 @@ void ipoib_mcast_join_task(struct work_struct *work) | |||
| 620 | /* Found the next unjoined group */ | 630 | /* Found the next unjoined group */ |
| 621 | init_completion(&mcast->done); | 631 | init_completion(&mcast->done); |
| 622 | set_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags); | 632 | set_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags); |
| 623 | spin_unlock_irq(&priv->lock); | 633 | if (ipoib_mcast_join(dev, mcast)) { |
| 624 | ipoib_mcast_join(dev, mcast); | 634 | spin_unlock_irq(&priv->lock); |
| 625 | spin_lock_irq(&priv->lock); | 635 | return; |
| 636 | } | ||
| 626 | } else if (!delay_until || | 637 | } else if (!delay_until || |
| 627 | time_before(mcast->delay_until, delay_until)) | 638 | time_before(mcast->delay_until, delay_until)) |
| 628 | delay_until = mcast->delay_until; | 639 | delay_until = mcast->delay_until; |
| @@ -641,10 +652,9 @@ out: | |||
| 641 | if (mcast) { | 652 | if (mcast) { |
| 642 | init_completion(&mcast->done); | 653 | init_completion(&mcast->done); |
| 643 | set_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags); | 654 | set_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags); |
| 655 | ipoib_mcast_join(dev, mcast); | ||
| 644 | } | 656 | } |
| 645 | spin_unlock_irq(&priv->lock); | 657 | spin_unlock_irq(&priv->lock); |
| 646 | if (mcast) | ||
| 647 | ipoib_mcast_join(dev, mcast); | ||
| 648 | } | 658 | } |
| 649 | 659 | ||
| 650 | int ipoib_mcast_start_thread(struct net_device *dev) | 660 | int ipoib_mcast_start_thread(struct net_device *dev) |
