Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=8d1cc86a6278687efbab7b8c294ab01efe4d4231
Commit:     8d1cc86a6278687efbab7b8c294ab01efe4d4231
Parent:     ed23a72778f3dbd465e55b06fe31629e7e1dd2f3
Author:     Roland Dreier <[EMAIL PROTECTED]>
AuthorDate: Sun May 6 21:05:32 2007 -0700
Committer:  Roland Dreier <[EMAIL PROTECTED]>
CommitDate: Sun May 6 21:18:11 2007 -0700

    IPoIB: Convert to NAPI
    
    Convert the IP-over-InfiniBand network device driver over to using
    NAPI to handle completions for the main CQ.  This covers all receives
    as well as datagram mode sends; send completions for connected mode
    connections are still handled from interrupt context.
    
    Signed-off-by: Roland Dreier <[EMAIL PROTECTED]>
---
 drivers/infiniband/ulp/ipoib/ipoib.h      |    1 +
 drivers/infiniband/ulp/ipoib/ipoib_cm.c   |    2 +-
 drivers/infiniband/ulp/ipoib/ipoib_ib.c   |   89 ++++++++++++++++++++++------
 drivers/infiniband/ulp/ipoib/ipoib_main.c |    2 +
 4 files changed, 74 insertions(+), 20 deletions(-)

diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h 
b/drivers/infiniband/ulp/ipoib/ipoib.h
index fd55826..15867af 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib.h
+++ b/drivers/infiniband/ulp/ipoib/ipoib.h
@@ -311,6 +311,7 @@ extern struct workqueue_struct *ipoib_workqueue;
 
 /* functions */
 
+int ipoib_poll(struct net_device *dev, int *budget);
 void ipoib_ib_completion(struct ib_cq *cq, void *dev_ptr);
 
 struct ipoib_ah *ipoib_create_ah(struct net_device *dev,
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_cm.c 
b/drivers/infiniband/ulp/ipoib/ipoib_cm.c
index b8089a0..785bc85 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_cm.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_cm.c
@@ -416,7 +416,7 @@ void ipoib_cm_handle_rx_wc(struct net_device *dev, struct 
ib_wc *wc)
        skb->dev = dev;
        /* XXX get correct PACKET_ type here */
        skb->pkt_type = PACKET_HOST;
-       netif_rx_ni(skb);
+       netif_receive_skb(skb);
 
 repost:
        if (unlikely(ipoib_cm_post_receive(dev, wr_id)))
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c 
b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
index 1bdb910..68d72c6 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
@@ -226,7 +226,7 @@ static void ipoib_ib_handle_rx_wc(struct net_device *dev, 
struct ib_wc *wc)
                skb->dev = dev;
                /* XXX get correct PACKET_ type here */
                skb->pkt_type = PACKET_HOST;
-               netif_rx_ni(skb);
+               netif_receive_skb(skb);
        } else {
                ipoib_dbg_data(priv, "dropping loopback packet\n");
                dev_kfree_skb_any(skb);
@@ -280,28 +280,63 @@ static void ipoib_ib_handle_tx_wc(struct net_device *dev, 
struct ib_wc *wc)
                           wc->status, wr_id, wc->vendor_err);
 }
 
-static void ipoib_ib_handle_wc(struct net_device *dev, struct ib_wc *wc)
+int ipoib_poll(struct net_device *dev, int *budget)
 {
-       if (wc->wr_id & IPOIB_CM_OP_SRQ)
-               ipoib_cm_handle_rx_wc(dev, wc);
-       else if (wc->wr_id & IPOIB_OP_RECV)
-               ipoib_ib_handle_rx_wc(dev, wc);
-       else
-               ipoib_ib_handle_tx_wc(dev, wc);
+       struct ipoib_dev_priv *priv = netdev_priv(dev);
+       int max = min(*budget, dev->quota);
+       int done;
+       int t;
+       int empty;
+       int n, i;
+
+       done  = 0;
+       empty = 0;
+
+       while (max) {
+               t = min(IPOIB_NUM_WC, max);
+               n = ib_poll_cq(priv->cq, t, priv->ibwc);
+
+               for (i = 0; i < n; ++i) {
+                       struct ib_wc *wc = priv->ibwc + i;
+
+                       if (wc->wr_id & IPOIB_CM_OP_SRQ) {
+                               ++done;
+                               --max;
+                               ipoib_cm_handle_rx_wc(dev, wc);
+                       } else if (wc->wr_id & IPOIB_OP_RECV) {
+                               ++done;
+                               --max;
+                               ipoib_ib_handle_rx_wc(dev, wc);
+                       } else
+                               ipoib_ib_handle_tx_wc(dev, wc);
+               }
+
+               if (n != t) {
+                       empty = 1;
+                       break;
+               }
+       }
+
+       dev->quota -= done;
+       *budget    -= done;
+
+       if (empty) {
+               netif_rx_complete(dev);
+               if (unlikely(ib_req_notify_cq(priv->cq,
+                                             IB_CQ_NEXT_COMP |
+                                             IB_CQ_REPORT_MISSED_EVENTS)) &&
+                   netif_rx_reschedule(dev, 0))
+                       return 1;
+
+               return 0;
+       }
+
+       return 1;
 }
 
 void ipoib_ib_completion(struct ib_cq *cq, void *dev_ptr)
 {
-       struct net_device *dev = (struct net_device *) dev_ptr;
-       struct ipoib_dev_priv *priv = netdev_priv(dev);
-       int n, i;
-
-       ib_req_notify_cq(cq, IB_CQ_NEXT_COMP);
-       do {
-               n = ib_poll_cq(cq, IPOIB_NUM_WC, priv->ibwc);
-               for (i = 0; i < n; ++i)
-                       ipoib_ib_handle_wc(dev, priv->ibwc + i);
-       } while (n == IPOIB_NUM_WC);
+       netif_rx_schedule(dev_ptr);
 }
 
 static inline int post_send(struct ipoib_dev_priv *priv,
@@ -514,9 +549,10 @@ int ipoib_ib_dev_stop(struct net_device *dev)
        struct ib_qp_attr qp_attr;
        unsigned long begin;
        struct ipoib_tx_buf *tx_req;
-       int i;
+       int i, n;
 
        clear_bit(IPOIB_FLAG_INITIALIZED, &priv->flags);
+       netif_poll_disable(dev);
 
        ipoib_cm_dev_stop(dev);
 
@@ -568,6 +604,18 @@ int ipoib_ib_dev_stop(struct net_device *dev)
                        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);
+
                msleep(1);
        }
 
@@ -596,6 +644,9 @@ timeout:
                msleep(1);
        }
 
+       netif_poll_enable(dev);
+       ib_req_notify_cq(priv->cq, IB_CQ_NEXT_COMP);
+
        return 0;
 }
 
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c 
b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index b4c380c..0a428f2 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -948,6 +948,8 @@ static void ipoib_setup(struct net_device *dev)
        dev->hard_header         = ipoib_hard_header;
        dev->set_multicast_list  = ipoib_set_mcast_list;
        dev->neigh_setup         = ipoib_neigh_setup_dev;
+       dev->poll                = ipoib_poll;
+       dev->weight              = 100;
 
        dev->watchdog_timeo      = HZ;
 
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to