aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorRoland Dreier <rolandd@cisco.com>2007-05-07 00:05:32 -0400
committerRoland Dreier <rolandd@cisco.com>2007-05-07 00:18:11 -0400
commit8d1cc86a6278687efbab7b8c294ab01efe4d4231 (patch)
tree6bbbb23fd44c08b709275a2918d937c27850bb23 /drivers
parented23a72778f3dbd465e55b06fe31629e7e1dd2f3 (diff)
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 <rolandd@cisco.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib.h1
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_cm.c2
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_ib.c89
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_main.c2
4 files changed, 74 insertions, 20 deletions
diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h
index fd558267d1cb..15867af33c44 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;
311 311
312/* functions */ 312/* functions */
313 313
314int ipoib_poll(struct net_device *dev, int *budget);
314void ipoib_ib_completion(struct ib_cq *cq, void *dev_ptr); 315void ipoib_ib_completion(struct ib_cq *cq, void *dev_ptr);
315 316
316struct ipoib_ah *ipoib_create_ah(struct net_device *dev, 317struct 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 b8089a041581..785bc8505f2a 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)
416 skb->dev = dev; 416 skb->dev = dev;
417 /* XXX get correct PACKET_ type here */ 417 /* XXX get correct PACKET_ type here */
418 skb->pkt_type = PACKET_HOST; 418 skb->pkt_type = PACKET_HOST;
419 netif_rx_ni(skb); 419 netif_receive_skb(skb);
420 420
421repost: 421repost:
422 if (unlikely(ipoib_cm_post_receive(dev, wr_id))) 422 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 1bdb9101911a..68d72c6f7ffb 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)
226 skb->dev = dev; 226 skb->dev = dev;
227 /* XXX get correct PACKET_ type here */ 227 /* XXX get correct PACKET_ type here */
228 skb->pkt_type = PACKET_HOST; 228 skb->pkt_type = PACKET_HOST;
229 netif_rx_ni(skb); 229 netif_receive_skb(skb);
230 } else { 230 } else {
231 ipoib_dbg_data(priv, "dropping loopback packet\n"); 231 ipoib_dbg_data(priv, "dropping loopback packet\n");
232 dev_kfree_skb_any(skb); 232 dev_kfree_skb_any(skb);
@@ -280,28 +280,63 @@ static void ipoib_ib_handle_tx_wc(struct net_device *dev, struct ib_wc *wc)
280 wc->status, wr_id, wc->vendor_err); 280 wc->status, wr_id, wc->vendor_err);
281} 281}
282 282
283static void ipoib_ib_handle_wc(struct net_device *dev, struct ib_wc *wc) 283int ipoib_poll(struct net_device *dev, int *budget)
284{ 284{
285 if (wc->wr_id & IPOIB_CM_OP_SRQ) 285 struct ipoib_dev_priv *priv = netdev_priv(dev);
286 ipoib_cm_handle_rx_wc(dev, wc); 286 int max = min(*budget, dev->quota);
287 else if (wc->wr_id & IPOIB_OP_RECV) 287 int done;
288 ipoib_ib_handle_rx_wc(dev, wc); 288 int t;
289 else 289 int empty;
290 ipoib_ib_handle_tx_wc(dev, wc); 290 int n, i;
291
292 done = 0;
293 empty = 0;
294
295 while (max) {
296 t = min(IPOIB_NUM_WC, max);
297 n = ib_poll_cq(priv->cq, t, priv->ibwc);
298
299 for (i = 0; i < n; ++i) {
300 struct ib_wc *wc = priv->ibwc + i;
301
302 if (wc->wr_id & IPOIB_CM_OP_SRQ) {
303 ++done;
304 --max;
305 ipoib_cm_handle_rx_wc(dev, wc);
306 } else if (wc->wr_id & IPOIB_OP_RECV) {
307 ++done;
308 --max;
309 ipoib_ib_handle_rx_wc(dev, wc);
310 } else
311 ipoib_ib_handle_tx_wc(dev, wc);
312 }
313
314 if (n != t) {
315 empty = 1;
316 break;
317 }
318 }
319
320 dev->quota -= done;
321 *budget -= done;
322
323 if (empty) {
324 netif_rx_complete(dev);
325 if (unlikely(ib_req_notify_cq(priv->cq,
326 IB_CQ_NEXT_COMP |
327 IB_CQ_REPORT_MISSED_EVENTS)) &&
328 netif_rx_reschedule(dev, 0))
329 return 1;
330
331 return 0;
332 }
333
334 return 1;
291} 335}
292 336
293void ipoib_ib_completion(struct ib_cq *cq, void *dev_ptr) 337void ipoib_ib_completion(struct ib_cq *cq, void *dev_ptr)
294{ 338{
295 struct net_device *dev = (struct net_device *) dev_ptr; 339 netif_rx_schedule(dev_ptr);
296 struct ipoib_dev_priv *priv = netdev_priv(dev);
297 int n, i;
298
299 ib_req_notify_cq(cq, IB_CQ_NEXT_COMP);
300 do {
301 n = ib_poll_cq(cq, IPOIB_NUM_WC, priv->ibwc);
302 for (i = 0; i < n; ++i)
303 ipoib_ib_handle_wc(dev, priv->ibwc + i);
304 } while (n == IPOIB_NUM_WC);
305} 340}
306 341
307static inline int post_send(struct ipoib_dev_priv *priv, 342static inline int post_send(struct ipoib_dev_priv *priv,
@@ -514,9 +549,10 @@ int ipoib_ib_dev_stop(struct net_device *dev)
514 struct ib_qp_attr qp_attr; 549 struct ib_qp_attr qp_attr;
515 unsigned long begin; 550 unsigned long begin;
516 struct ipoib_tx_buf *tx_req; 551 struct ipoib_tx_buf *tx_req;
517 int i; 552 int i, n;
518 553
519 clear_bit(IPOIB_FLAG_INITIALIZED, &priv->flags); 554 clear_bit(IPOIB_FLAG_INITIALIZED, &priv->flags);
555 netif_poll_disable(dev);
520 556
521 ipoib_cm_dev_stop(dev); 557 ipoib_cm_dev_stop(dev);
522 558
@@ -568,6 +604,18 @@ int ipoib_ib_dev_stop(struct net_device *dev)
568 goto timeout; 604 goto timeout;
569 } 605 }
570 606
607 do {
608 n = ib_poll_cq(priv->cq, IPOIB_NUM_WC, priv->ibwc);
609 for (i = 0; i < n; ++i) {
610 if (priv->ibwc[i].wr_id & IPOIB_CM_OP_SRQ)
611 ipoib_cm_handle_rx_wc(dev, priv->ibwc + i);
612 else if (priv->ibwc[i].wr_id & IPOIB_OP_RECV)
613 ipoib_ib_handle_rx_wc(dev, priv->ibwc + i);
614 else
615 ipoib_ib_handle_tx_wc(dev, priv->ibwc + i);
616 }
617 } while (n == IPOIB_NUM_WC);
618
571 msleep(1); 619 msleep(1);
572 } 620 }
573 621
@@ -596,6 +644,9 @@ timeout:
596 msleep(1); 644 msleep(1);
597 } 645 }
598 646
647 netif_poll_enable(dev);
648 ib_req_notify_cq(priv->cq, IB_CQ_NEXT_COMP);
649
599 return 0; 650 return 0;
600} 651}
601 652
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index b4c380c5a3ba..0a428f2b05c7 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)
948 dev->hard_header = ipoib_hard_header; 948 dev->hard_header = ipoib_hard_header;
949 dev->set_multicast_list = ipoib_set_mcast_list; 949 dev->set_multicast_list = ipoib_set_mcast_list;
950 dev->neigh_setup = ipoib_neigh_setup_dev; 950 dev->neigh_setup = ipoib_neigh_setup_dev;
951 dev->poll = ipoib_poll;
952 dev->weight = 100;
951 953
952 dev->watchdog_timeo = HZ; 954 dev->watchdog_timeo = HZ;
953 955