diff options
Diffstat (limited to 'drivers/infiniband/ulp/ipoib')
-rw-r--r-- | drivers/infiniband/ulp/ipoib/ipoib.h | 1 | ||||
-rw-r--r-- | drivers/infiniband/ulp/ipoib/ipoib_cm.c | 14 | ||||
-rw-r--r-- | drivers/infiniband/ulp/ipoib/ipoib_ib.c | 89 | ||||
-rw-r--r-- | drivers/infiniband/ulp/ipoib/ipoib_main.c | 2 | ||||
-rw-r--r-- | drivers/infiniband/ulp/ipoib/ipoib_verbs.c | 2 |
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 | ||
313 | int ipoib_poll(struct net_device *dev, int *budget); | ||
313 | void ipoib_ib_completion(struct ib_cq *cq, void *dev_ptr); | 314 | void ipoib_ib_completion(struct ib_cq *cq, void *dev_ptr); |
314 | 315 | ||
315 | struct ipoib_ah *ipoib_create_ah(struct net_device *dev, | 316 | 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 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 | ||
421 | repost: | 421 | repost: |
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 | ||
283 | static void ipoib_ib_handle_wc(struct net_device *dev, struct ib_wc *wc) | 283 | int 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 | ||
293 | void ipoib_ib_completion(struct ib_cq *cq, void *dev_ptr) | 337 | void 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 | ||
307 | static inline int post_send(struct ipoib_dev_priv *priv, | 342 | static 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; |