aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_multicast.c24
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
459static void ipoib_mcast_join(struct net_device *dev, struct ipoib_mcast *mcast) 459/*
460 * Caller must hold 'priv->lock'
461 */
462static 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
544void ipoib_mcast_join_task(struct work_struct *work) 554void 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
650int ipoib_mcast_start_thread(struct net_device *dev) 660int ipoib_mcast_start_thread(struct net_device *dev)