diff options
author | Michael S. Tsirkin <mst@mellanox.co.il> | 2006-02-07 19:37:08 -0500 |
---|---|---|
committer | Roland Dreier <rolandd@cisco.com> | 2006-02-07 19:37:08 -0500 |
commit | 479a079663bd4c5f3d2714643b1b8c406aaba3e0 (patch) | |
tree | e484f9a2dce6ee68f1c328d54f18acbf137c1999 /drivers/infiniband | |
parent | 8cf3f04f45694db0699f608c0e3fb550c607cc88 (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/infiniband')
-rw-r--r-- | drivers/infiniband/ulp/ipoib/ipoib.h | 1 | ||||
-rw-r--r-- | drivers/infiniband/ulp/ipoib/ipoib_multicast.c | 15 |
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 | ||
771 | unlock: | ||
757 | spin_unlock(&priv->lock); | 772 | spin_unlock(&priv->lock); |
758 | } | 773 | } |
759 | 774 | ||