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 | |
| 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>
| -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 | } |
