aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/ulp/ipoib
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/infiniband/ulp/ipoib')
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib.h1
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_cm.c14
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_ib.c89
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_main.c2
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_verbs.c2
5 files changed, 83 insertions, 25 deletions
diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h
index d8f6bb4f53fc..87310eeb6df0 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib.h
+++ b/drivers/infiniband/ulp/ipoib/ipoib.h
@@ -310,6 +310,7 @@ extern struct workqueue_struct *ipoib_workqueue;
310 310
311/* functions */ 311/* functions */
312 312
313int ipoib_poll(struct net_device *dev, int *budget);
313void ipoib_ib_completion(struct ib_cq *cq, void *dev_ptr); 314void ipoib_ib_completion(struct ib_cq *cq, void *dev_ptr);
314 315
315struct ipoib_ah *ipoib_create_ah(struct net_device *dev, 316struct 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 0c4e59b906cd..785bc8505f2a 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_cm.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_cm.c
@@ -370,7 +370,7 @@ void ipoib_cm_handle_rx_wc(struct net_device *dev, struct ib_wc *wc)
370 370
371 if (!likely(wr_id & IPOIB_CM_RX_UPDATE_MASK)) { 371 if (!likely(wr_id & IPOIB_CM_RX_UPDATE_MASK)) {
372 p = wc->qp->qp_context; 372 p = wc->qp->qp_context;
373 if (time_after_eq(jiffies, p->jiffies + IPOIB_CM_RX_UPDATE_TIME)) { 373 if (p && time_after_eq(jiffies, p->jiffies + IPOIB_CM_RX_UPDATE_TIME)) {
374 spin_lock_irqsave(&priv->lock, flags); 374 spin_lock_irqsave(&priv->lock, flags);
375 p->jiffies = jiffies; 375 p->jiffies = jiffies;
376 /* Move this entry to list head, but do 376 /* Move this entry to list head, but do
@@ -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)))
@@ -592,7 +592,9 @@ int ipoib_cm_dev_open(struct net_device *dev)
592 priv->cm.id = ib_create_cm_id(priv->ca, ipoib_cm_rx_handler, dev); 592 priv->cm.id = ib_create_cm_id(priv->ca, ipoib_cm_rx_handler, dev);
593 if (IS_ERR(priv->cm.id)) { 593 if (IS_ERR(priv->cm.id)) {
594 printk(KERN_WARNING "%s: failed to create CM ID\n", priv->ca->name); 594 printk(KERN_WARNING "%s: failed to create CM ID\n", priv->ca->name);
595 return IS_ERR(priv->cm.id); 595 ret = PTR_ERR(priv->cm.id);
596 priv->cm.id = NULL;
597 return ret;
596 } 598 }
597 599
598 ret = ib_cm_listen(priv->cm.id, cpu_to_be64(IPOIB_CM_IETF_ID | priv->qp->qp_num), 600 ret = ib_cm_listen(priv->cm.id, cpu_to_be64(IPOIB_CM_IETF_ID | priv->qp->qp_num),
@@ -601,6 +603,7 @@ int ipoib_cm_dev_open(struct net_device *dev)
601 printk(KERN_WARNING "%s: failed to listen on ID 0x%llx\n", priv->ca->name, 603 printk(KERN_WARNING "%s: failed to listen on ID 0x%llx\n", priv->ca->name,
602 IPOIB_CM_IETF_ID | priv->qp->qp_num); 604 IPOIB_CM_IETF_ID | priv->qp->qp_num);
603 ib_destroy_cm_id(priv->cm.id); 605 ib_destroy_cm_id(priv->cm.id);
606 priv->cm.id = NULL;
604 return ret; 607 return ret;
605 } 608 }
606 return 0; 609 return 0;
@@ -611,10 +614,11 @@ void ipoib_cm_dev_stop(struct net_device *dev)
611 struct ipoib_dev_priv *priv = netdev_priv(dev); 614 struct ipoib_dev_priv *priv = netdev_priv(dev);
612 struct ipoib_cm_rx *p; 615 struct ipoib_cm_rx *p;
613 616
614 if (!IPOIB_CM_SUPPORTED(dev->dev_addr)) 617 if (!IPOIB_CM_SUPPORTED(dev->dev_addr) || !priv->cm.id)
615 return; 618 return;
616 619
617 ib_destroy_cm_id(priv->cm.id); 620 ib_destroy_cm_id(priv->cm.id);
621 priv->cm.id = NULL;
618 spin_lock_irq(&priv->lock); 622 spin_lock_irq(&priv->lock);
619 while (!list_empty(&priv->cm.passive_ids)) { 623 while (!list_empty(&priv->cm.passive_ids)) {
620 p = list_entry(priv->cm.passive_ids.next, typeof(*p), list); 624 p = list_entry(priv->cm.passive_ids.next, typeof(*p), list);
@@ -789,7 +793,7 @@ static int ipoib_cm_tx_init(struct ipoib_cm_tx *p, u32 qpn,
789 } 793 }
790 794
791 p->cq = ib_create_cq(priv->ca, ipoib_cm_tx_completion, NULL, p, 795 p->cq = ib_create_cq(priv->ca, ipoib_cm_tx_completion, NULL, p,
792 ipoib_sendq_size + 1); 796 ipoib_sendq_size + 1, 0);
793 if (IS_ERR(p->cq)) { 797 if (IS_ERR(p->cq)) {
794 ret = PTR_ERR(p->cq); 798 ret = PTR_ERR(p->cq);
795 ipoib_warn(priv, "failed to allocate tx cq: %d\n", ret); 799 ipoib_warn(priv, "failed to allocate tx cq: %d\n", ret);
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
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_verbs.c b/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
index 7f3ec205e35f..5c3c6a43a52b 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
@@ -187,7 +187,7 @@ int ipoib_transport_dev_init(struct net_device *dev, struct ib_device *ca)
187 if (!ret) 187 if (!ret)
188 size += ipoib_recvq_size; 188 size += ipoib_recvq_size;
189 189
190 priv->cq = ib_create_cq(priv->ca, ipoib_ib_completion, NULL, dev, size); 190 priv->cq = ib_create_cq(priv->ca, ipoib_ib_completion, NULL, dev, size, 0);
191 if (IS_ERR(priv->cq)) { 191 if (IS_ERR(priv->cq)) {
192 printk(KERN_WARNING "%s: failed to create CQ\n", ca->name); 192 printk(KERN_WARNING "%s: failed to create CQ\n", ca->name);
193 goto out_free_mr; 193 goto out_free_mr;