From: Roland Dreier Date: Tue, 20 Sep 2005 17:52:04 +0000 (-0700) Subject: [PATCH] IPoIB: Don't flush workqueue from within workqueue X-Git-Tag: v2.6.14-rc3~150^2~1 X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8d2cae0651502028bf64844508ab18528bbd65c2;p=linux-2.6 [PATCH] IPoIB: Don't flush workqueue from within workqueue ipoib_mcast_restart_task() is always called from within the single-threaded IPoIB workqueue, so flushing the workqueue from within the function can lead to a recursion overflow. But since we're running in a single-threaded workqueue, we're already synchronized against other items in the workqueue, so just get rid of the flush in ipoib_mcast_restart_task(). Signed-off-by: Roland Dreier --- diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h index bea960b819..4ea1c1ca85 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib.h +++ b/drivers/infiniband/ulp/ipoib/ipoib.h @@ -257,7 +257,7 @@ void ipoib_mcast_send(struct net_device *dev, union ib_gid *mgid, void ipoib_mcast_restart_task(void *dev_ptr); int ipoib_mcast_start_thread(struct net_device *dev); -int ipoib_mcast_stop_thread(struct net_device *dev); +int ipoib_mcast_stop_thread(struct net_device *dev, int flush); void ipoib_mcast_dev_down(struct net_device *dev); void ipoib_mcast_dev_flush(struct net_device *dev); diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c index ef0e389486..f7440096b5 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c @@ -432,7 +432,7 @@ int ipoib_ib_dev_down(struct net_device *dev) flush_workqueue(ipoib_workqueue); } - ipoib_mcast_stop_thread(dev); + ipoib_mcast_stop_thread(dev, 1); /* * Flush the multicast groups first so we stop any multicast joins. The @@ -599,7 +599,7 @@ void ipoib_ib_dev_cleanup(struct net_device *dev) ipoib_dbg(priv, "cleaning up ib_dev\n"); - ipoib_mcast_stop_thread(dev); + ipoib_mcast_stop_thread(dev, 1); /* Delete the broadcast address and the local address */ ipoib_mcast_dev_down(dev); diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c index 3aab4d85ab..36ce29836b 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c @@ -598,7 +598,7 @@ int ipoib_mcast_start_thread(struct net_device *dev) return 0; } -int ipoib_mcast_stop_thread(struct net_device *dev) +int ipoib_mcast_stop_thread(struct net_device *dev, int flush) { struct ipoib_dev_priv *priv = netdev_priv(dev); struct ipoib_mcast *mcast; @@ -610,7 +610,8 @@ int ipoib_mcast_stop_thread(struct net_device *dev) cancel_delayed_work(&priv->mcast_task); up(&mcast_mutex); - flush_workqueue(ipoib_workqueue); + if (flush) + flush_workqueue(ipoib_workqueue); if (priv->broadcast && priv->broadcast->query) { ib_sa_cancel_query(priv->broadcast->query_id, priv->broadcast->query); @@ -832,7 +833,7 @@ void ipoib_mcast_restart_task(void *dev_ptr) ipoib_dbg_mcast(priv, "restarting multicast task\n"); - ipoib_mcast_stop_thread(dev); + ipoib_mcast_stop_thread(dev, 0); spin_lock_irqsave(&priv->lock, flags);