aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/ulp/ipoib
diff options
context:
space:
mode:
authorDoug Ledford <dledford@redhat.com>2015-02-21 19:26:59 -0500
committerDoug Ledford <dledford@redhat.com>2015-04-15 16:06:17 -0400
commite135106fac9525352feb8e49077c8f46c3eaf288 (patch)
treead686daa6638603a7df17dfe0dc0f2c1642f4a37 /drivers/infiniband/ulp/ipoib
parentc841e12add6926d64aa608687893465330b5a03e (diff)
IB/ipoib: factor out ah flushing
Create a an ipoib_flush_ah and ipoib_stop_ah routines to use at appropriate times to flush out all remaining ah entries before we shut the device down. Because neighbors and mcast entries can each have a reference on any given ah, we must make sure to free all of those first before our ah will actually have a 0 refcount and be able to be reaped. This factoring is needed in preparation for having per-device work queues. The original per-device workqueue code resulted in the following error message: <ibdev>: ib_dealloc_pd failed That error was tracked down to this issue. With the changes to which workqueues were flushed when, there were no flushes of the per device workqueue after the last ah's were freed, resulting in an attempt to dealloc the pd with outstanding resources still allocated. This code puts the explicit flushes in the needed places to avoid that problem. Signed-off-by: Doug Ledford <dledford@redhat.com>
Diffstat (limited to 'drivers/infiniband/ulp/ipoib')
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_ib.c46
1 files changed, 28 insertions, 18 deletions
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
index 72626c348174..cb02466a0eb9 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
@@ -659,6 +659,24 @@ void ipoib_reap_ah(struct work_struct *work)
659 round_jiffies_relative(HZ)); 659 round_jiffies_relative(HZ));
660} 660}
661 661
662static void ipoib_flush_ah(struct net_device *dev, int flush)
663{
664 struct ipoib_dev_priv *priv = netdev_priv(dev);
665
666 cancel_delayed_work(&priv->ah_reap_task);
667 if (flush)
668 flush_workqueue(ipoib_workqueue);
669 ipoib_reap_ah(&priv->ah_reap_task.work);
670}
671
672static void ipoib_stop_ah(struct net_device *dev, int flush)
673{
674 struct ipoib_dev_priv *priv = netdev_priv(dev);
675
676 set_bit(IPOIB_STOP_REAPER, &priv->flags);
677 ipoib_flush_ah(dev, flush);
678}
679
662static void ipoib_ib_tx_timer_func(unsigned long ctx) 680static void ipoib_ib_tx_timer_func(unsigned long ctx)
663{ 681{
664 drain_tx_cq((struct net_device *)ctx); 682 drain_tx_cq((struct net_device *)ctx);
@@ -877,24 +895,7 @@ timeout:
877 if (ib_modify_qp(priv->qp, &qp_attr, IB_QP_STATE)) 895 if (ib_modify_qp(priv->qp, &qp_attr, IB_QP_STATE))
878 ipoib_warn(priv, "Failed to modify QP to RESET state\n"); 896 ipoib_warn(priv, "Failed to modify QP to RESET state\n");
879 897
880 /* Wait for all AHs to be reaped */ 898 ipoib_flush_ah(dev, flush);
881 set_bit(IPOIB_STOP_REAPER, &priv->flags);
882 cancel_delayed_work(&priv->ah_reap_task);
883 if (flush)
884 flush_workqueue(ipoib_workqueue);
885
886 begin = jiffies;
887
888 while (!list_empty(&priv->dead_ahs)) {
889 __ipoib_reap_ah(dev);
890
891 if (time_after(jiffies, begin + HZ)) {
892 ipoib_warn(priv, "timing out; will leak address handles\n");
893 break;
894 }
895
896 msleep(1);
897 }
898 899
899 ib_req_notify_cq(priv->recv_cq, IB_CQ_NEXT_COMP); 900 ib_req_notify_cq(priv->recv_cq, IB_CQ_NEXT_COMP);
900 901
@@ -1037,6 +1038,7 @@ static void __ipoib_ib_dev_flush(struct ipoib_dev_priv *priv,
1037 if (level == IPOIB_FLUSH_LIGHT) { 1038 if (level == IPOIB_FLUSH_LIGHT) {
1038 ipoib_mark_paths_invalid(dev); 1039 ipoib_mark_paths_invalid(dev);
1039 ipoib_mcast_dev_flush(dev); 1040 ipoib_mcast_dev_flush(dev);
1041 ipoib_flush_ah(dev, 0);
1040 } 1042 }
1041 1043
1042 if (level >= IPOIB_FLUSH_NORMAL) 1044 if (level >= IPOIB_FLUSH_NORMAL)
@@ -1100,6 +1102,14 @@ void ipoib_ib_dev_cleanup(struct net_device *dev)
1100 ipoib_mcast_stop_thread(dev, 1); 1102 ipoib_mcast_stop_thread(dev, 1);
1101 ipoib_mcast_dev_flush(dev); 1103 ipoib_mcast_dev_flush(dev);
1102 1104
1105 /*
1106 * All of our ah references aren't free until after
1107 * ipoib_mcast_dev_flush(), ipoib_flush_paths, and
1108 * the neighbor garbage collection is stopped and reaped.
1109 * That should all be done now, so make a final ah flush.
1110 */
1111 ipoib_stop_ah(dev, 1);
1112
1103 ipoib_transport_dev_cleanup(dev); 1113 ipoib_transport_dev_cleanup(dev);
1104} 1114}
1105 1115