diff options
author | Eli Cohen <eli@mellanox.co.il> | 2006-04-05 07:59:40 -0400 |
---|---|---|
committer | Roland Dreier <rolandd@cisco.com> | 2006-04-10 12:43:58 -0400 |
commit | f2de3b06126ddb07d0e4617225d74dce0855add3 (patch) | |
tree | 21a62b2115804688d700c01ed2ede87413b5d9d1 /drivers | |
parent | bf6a9e31cfa768ce0a8e18474b3ca808641d9243 (diff) |
IPoIB: Wait for join to finish before freeing mcast struct
ipoib_mcast_restart_task() might free an mcast object while a join
request is still outstanding, leading to an oops when the query
completes. Fix this by waiting for query to complete, similar to what
ipoib_stop_thread() is doing. The wait for mcast completion code is
consolidated in wait_for_mcast_join().
Signed-off-by: Eli Cohen <eli@mellanox.co.il>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/infiniband/ulp/ipoib/ipoib_multicast.c | 41 |
1 files changed, 20 insertions, 21 deletions
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c index 07b9826b5193..1dae4b238252 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c | |||
@@ -609,6 +609,22 @@ int ipoib_mcast_start_thread(struct net_device *dev) | |||
609 | return 0; | 609 | return 0; |
610 | } | 610 | } |
611 | 611 | ||
612 | static void wait_for_mcast_join(struct ipoib_dev_priv *priv, | ||
613 | struct ipoib_mcast *mcast) | ||
614 | { | ||
615 | spin_lock_irq(&priv->lock); | ||
616 | if (mcast && mcast->query) { | ||
617 | ib_sa_cancel_query(mcast->query_id, mcast->query); | ||
618 | mcast->query = NULL; | ||
619 | spin_unlock_irq(&priv->lock); | ||
620 | ipoib_dbg_mcast(priv, "waiting for MGID " IPOIB_GID_FMT "\n", | ||
621 | IPOIB_GID_ARG(mcast->mcmember.mgid)); | ||
622 | wait_for_completion(&mcast->done); | ||
623 | } | ||
624 | else | ||
625 | spin_unlock_irq(&priv->lock); | ||
626 | } | ||
627 | |||
612 | int ipoib_mcast_stop_thread(struct net_device *dev, int flush) | 628 | int ipoib_mcast_stop_thread(struct net_device *dev, int flush) |
613 | { | 629 | { |
614 | struct ipoib_dev_priv *priv = netdev_priv(dev); | 630 | struct ipoib_dev_priv *priv = netdev_priv(dev); |
@@ -628,28 +644,10 @@ int ipoib_mcast_stop_thread(struct net_device *dev, int flush) | |||
628 | if (flush) | 644 | if (flush) |
629 | flush_workqueue(ipoib_workqueue); | 645 | flush_workqueue(ipoib_workqueue); |
630 | 646 | ||
631 | spin_lock_irq(&priv->lock); | 647 | wait_for_mcast_join(priv, priv->broadcast); |
632 | if (priv->broadcast && priv->broadcast->query) { | ||
633 | ib_sa_cancel_query(priv->broadcast->query_id, priv->broadcast->query); | ||
634 | priv->broadcast->query = NULL; | ||
635 | spin_unlock_irq(&priv->lock); | ||
636 | ipoib_dbg_mcast(priv, "waiting for bcast\n"); | ||
637 | wait_for_completion(&priv->broadcast->done); | ||
638 | } else | ||
639 | spin_unlock_irq(&priv->lock); | ||
640 | 648 | ||
641 | list_for_each_entry(mcast, &priv->multicast_list, list) { | 649 | list_for_each_entry(mcast, &priv->multicast_list, list) |
642 | spin_lock_irq(&priv->lock); | 650 | wait_for_mcast_join(priv, mcast); |
643 | if (mcast->query) { | ||
644 | ib_sa_cancel_query(mcast->query_id, mcast->query); | ||
645 | mcast->query = NULL; | ||
646 | spin_unlock_irq(&priv->lock); | ||
647 | ipoib_dbg_mcast(priv, "waiting for MGID " IPOIB_GID_FMT "\n", | ||
648 | IPOIB_GID_ARG(mcast->mcmember.mgid)); | ||
649 | wait_for_completion(&mcast->done); | ||
650 | } else | ||
651 | spin_unlock_irq(&priv->lock); | ||
652 | } | ||
653 | 651 | ||
654 | return 0; | 652 | return 0; |
655 | } | 653 | } |
@@ -902,6 +900,7 @@ void ipoib_mcast_restart_task(void *dev_ptr) | |||
902 | 900 | ||
903 | /* We have to cancel outside of the spinlock */ | 901 | /* We have to cancel outside of the spinlock */ |
904 | list_for_each_entry_safe(mcast, tmcast, &remove_list, list) { | 902 | list_for_each_entry_safe(mcast, tmcast, &remove_list, list) { |
903 | wait_for_mcast_join(priv, mcast); | ||
905 | ipoib_mcast_leave(mcast->dev, mcast); | 904 | ipoib_mcast_leave(mcast->dev, mcast); |
906 | ipoib_mcast_free(mcast); | 905 | ipoib_mcast_free(mcast); |
907 | } | 906 | } |