IPoIB/cm: Drain cq in ipoib_cm_dev_stop()
authorMichael S. Tsirkin <mst@dev.mellanox.co.il>
Thu, 24 May 2007 15:32:46 +0000 (18:32 +0300)
committerRoland Dreier <rolandd@cisco.com>
Thu, 24 May 2007 21:02:40 +0000 (14:02 -0700)
Since NAPI polling is disabled while ipoib_cm_dev_stop() is running,
ipoib_cm_dev_stop() must poll the CQ itself in order to see the
packets draining.

Signed-off-by: Michael S. Tsirkin <mst@dev.mellanox.co.il>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
drivers/infiniband/ulp/ipoib/ipoib.h
drivers/infiniband/ulp/ipoib/ipoib_cm.c
drivers/infiniband/ulp/ipoib/ipoib_ib.c

index a0b3782c762504d957e63d018214ec700ed89734..158759e28a5bf3200872dde015de8181333da0ba 100644 (file)
@@ -429,6 +429,7 @@ int ipoib_vlan_delete(struct net_device *pdev, unsigned short pkey);
 
 void ipoib_pkey_poll(struct work_struct *work);
 int ipoib_pkey_dev_delay_open(struct net_device *dev);
+void ipoib_drain_cq(struct net_device *dev);
 
 #ifdef CONFIG_INFINIBAND_IPOIB_CM
 
index e8fcd628be73fcca1791b505c01471e0f0c42ca0..f133b56fd978dd4aefef36efe58ff849e06bb75e 100644 (file)
@@ -726,6 +726,7 @@ void ipoib_cm_dev_stop(struct net_device *dev)
                }
                spin_unlock_irq(&priv->lock);
                msleep(1);
+               ipoib_drain_cq(dev);
                spin_lock_irq(&priv->lock);
        }
 
index c1aad06eb4e9b0222457b5c7efc8fc146a39b839..8404f05b2b6eefd04a018b5da67698b65cfb09fd 100644 (file)
@@ -550,13 +550,30 @@ static int recvs_pending(struct net_device *dev)
        return pending;
 }
 
+void ipoib_drain_cq(struct net_device *dev)
+{
+       struct ipoib_dev_priv *priv = netdev_priv(dev);
+       int i, n;
+       do {
+               n = ib_poll_cq(priv->cq, IPOIB_NUM_WC, priv->ibwc);
+               for (i = 0; i < n; ++i) {
+                       if (priv->ibwc[i].wr_id & IPOIB_CM_OP_SRQ)
+                               ipoib_cm_handle_rx_wc(dev, priv->ibwc + i);
+                       else if (priv->ibwc[i].wr_id & IPOIB_OP_RECV)
+                               ipoib_ib_handle_rx_wc(dev, priv->ibwc + i);
+                       else
+                               ipoib_ib_handle_tx_wc(dev, priv->ibwc + i);
+               }
+       } while (n == IPOIB_NUM_WC);
+}
+
 int ipoib_ib_dev_stop(struct net_device *dev, int flush)
 {
        struct ipoib_dev_priv *priv = netdev_priv(dev);
        struct ib_qp_attr qp_attr;
        unsigned long begin;
        struct ipoib_tx_buf *tx_req;
-       int i, n;
+       int i;
 
        clear_bit(IPOIB_FLAG_INITIALIZED, &priv->flags);
        netif_poll_disable(dev);
@@ -611,17 +628,7 @@ int ipoib_ib_dev_stop(struct net_device *dev, int flush)
                        goto timeout;
                }
 
-               do {
-                       n = ib_poll_cq(priv->cq, IPOIB_NUM_WC, priv->ibwc);
-                       for (i = 0; i < n; ++i) {
-                               if (priv->ibwc[i].wr_id & IPOIB_CM_OP_SRQ)
-                                       ipoib_cm_handle_rx_wc(dev, priv->ibwc + i);
-                               else if (priv->ibwc[i].wr_id & IPOIB_OP_RECV)
-                                       ipoib_ib_handle_rx_wc(dev, priv->ibwc + i);
-                               else
-                                       ipoib_ib_handle_tx_wc(dev, priv->ibwc + i);
-                       }
-               } while (n == IPOIB_NUM_WC);
+               ipoib_drain_cq(dev);
 
                msleep(1);
        }