aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorMichael S. Tsirkin <mst@mellanox.co.il>2006-02-07 19:37:08 -0500
committerRoland Dreier <rolandd@cisco.com>2006-02-07 19:37:08 -0500
commit479a079663bd4c5f3d2714643b1b8c406aaba3e0 (patch)
treee484f9a2dce6ee68f1c328d54f18acbf137c1999 /drivers
parent8cf3f04f45694db0699f608c0e3fb550c607cc88 (diff)
IPoIB: Don't start send-only joins while multicast thread is stopped
Fix the following race scenario: - Device is up. - Port event or set mcast list triggers ipoib_mcast_stop_thread, this cancels the query and waits on mcast "done" completion. - Completion is called and "done" is set. - Meanwhile, ipoib_mcast_send arrives and starts a new query, re-initializing "done". Fix this by adding a "multicast started" bit and checking it before starting a send-only join. Signed-off-by: Michael S. Tsirkin <mst@mellanox.co.il> Signed-off-by: Roland Dreier <rolandd@cisco.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib.h1
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_multicast.c15
2 files changed, 16 insertions, 0 deletions
diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h
index e0a5412b7e68..2f85a9a831b1 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib.h
+++ b/drivers/infiniband/ulp/ipoib/ipoib.h
@@ -78,6 +78,7 @@ enum {
78 IPOIB_FLAG_SUBINTERFACE = 4, 78 IPOIB_FLAG_SUBINTERFACE = 4,
79 IPOIB_MCAST_RUN = 5, 79 IPOIB_MCAST_RUN = 5,
80 IPOIB_STOP_REAPER = 6, 80 IPOIB_STOP_REAPER = 6,
81 IPOIB_MCAST_STARTED = 7,
81 82
82 IPOIB_MAX_BACKOFF_SECONDS = 16, 83 IPOIB_MAX_BACKOFF_SECONDS = 16,
83 84
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
index ccaa0c387076..1c7148208ce8 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
@@ -601,6 +601,10 @@ int ipoib_mcast_start_thread(struct net_device *dev)
601 queue_work(ipoib_workqueue, &priv->mcast_task); 601 queue_work(ipoib_workqueue, &priv->mcast_task);
602 mutex_unlock(&mcast_mutex); 602 mutex_unlock(&mcast_mutex);
603 603
604 spin_lock_irq(&priv->lock);
605 set_bit(IPOIB_MCAST_STARTED, &priv->flags);
606 spin_unlock_irq(&priv->lock);
607
604 return 0; 608 return 0;
605} 609}
606 610
@@ -611,6 +615,10 @@ int ipoib_mcast_stop_thread(struct net_device *dev, int flush)
611 615
612 ipoib_dbg_mcast(priv, "stopping multicast thread\n"); 616 ipoib_dbg_mcast(priv, "stopping multicast thread\n");
613 617
618 spin_lock_irq(&priv->lock);
619 clear_bit(IPOIB_MCAST_STARTED, &priv->flags);
620 spin_unlock_irq(&priv->lock);
621
614 mutex_lock(&mcast_mutex); 622 mutex_lock(&mcast_mutex);
615 clear_bit(IPOIB_MCAST_RUN, &priv->flags); 623 clear_bit(IPOIB_MCAST_RUN, &priv->flags);
616 cancel_delayed_work(&priv->mcast_task); 624 cancel_delayed_work(&priv->mcast_task);
@@ -693,6 +701,12 @@ void ipoib_mcast_send(struct net_device *dev, union ib_gid *mgid,
693 */ 701 */
694 spin_lock(&priv->lock); 702 spin_lock(&priv->lock);
695 703
704 if (!test_bit(IPOIB_MCAST_STARTED, &priv->flags)) {
705 ++priv->stats.tx_dropped;
706 dev_kfree_skb_any(skb);
707 goto unlock;
708 }
709
696 mcast = __ipoib_mcast_find(dev, mgid); 710 mcast = __ipoib_mcast_find(dev, mgid);
697 if (!mcast) { 711 if (!mcast) {
698 /* Let's create a new send only group now */ 712 /* Let's create a new send only group now */
@@ -754,6 +768,7 @@ out:
754 ipoib_send(dev, skb, mcast->ah, IB_MULTICAST_QPN); 768 ipoib_send(dev, skb, mcast->ah, IB_MULTICAST_QPN);
755 } 769 }
756 770
771unlock:
757 spin_unlock(&priv->lock); 772 spin_unlock(&priv->lock);
758} 773}
759 774