diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-05-05 20:31:41 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-05-05 20:31:41 -0400 |
commit | a15306365a16380f3bafee9e181ba01231d4acd7 (patch) | |
tree | c5eb3756235ac7fe4ce540730b8d7480318c5953 /drivers/infiniband | |
parent | bb896afe2089575ca1bb1fbf3f07b934e1ba999b (diff) | |
parent | c5057ddccbcb4bf363af628d7963a7475f4114a7 (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/roland/infiniband
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/roland/infiniband:
mlx4_core: Support creation of FMRs with pages smaller than 4K
IB/ehca: Fix function return types
RDMA/cxgb3: Bump up the MPA connection setup timeout.
RDMA/cxgb3: Silently ignore close reply after abort.
RDMA/cxgb3: QP flush fixes
IB/ipoib: Fix transmit queue stalling forever
IB/mlx4: Fix off-by-one errors in calls to mlx4_ib_free_cq_buf()
Diffstat (limited to 'drivers/infiniband')
-rw-r--r-- | drivers/infiniband/hw/cxgb3/cxio_hal.c | 13 | ||||
-rw-r--r-- | drivers/infiniband/hw/cxgb3/cxio_hal.h | 4 | ||||
-rw-r--r-- | drivers/infiniband/hw/cxgb3/iwch_cm.c | 6 | ||||
-rw-r--r-- | drivers/infiniband/hw/cxgb3/iwch_qp.c | 13 | ||||
-rw-r--r-- | drivers/infiniband/hw/ehca/ehca_hca.c | 7 | ||||
-rw-r--r-- | drivers/infiniband/hw/mlx4/cq.c | 4 | ||||
-rw-r--r-- | drivers/infiniband/ulp/ipoib/ipoib.h | 2 | ||||
-rw-r--r-- | drivers/infiniband/ulp/ipoib/ipoib_ib.c | 47 | ||||
-rw-r--r-- | drivers/infiniband/ulp/ipoib/ipoib_verbs.c | 3 |
9 files changed, 74 insertions, 25 deletions
diff --git a/drivers/infiniband/hw/cxgb3/cxio_hal.c b/drivers/infiniband/hw/cxgb3/cxio_hal.c index ed2ee4ba4b7c..5fd8506a8657 100644 --- a/drivers/infiniband/hw/cxgb3/cxio_hal.c +++ b/drivers/infiniband/hw/cxgb3/cxio_hal.c | |||
@@ -359,9 +359,10 @@ static void insert_recv_cqe(struct t3_wq *wq, struct t3_cq *cq) | |||
359 | cq->sw_wptr++; | 359 | cq->sw_wptr++; |
360 | } | 360 | } |
361 | 361 | ||
362 | void cxio_flush_rq(struct t3_wq *wq, struct t3_cq *cq, int count) | 362 | int cxio_flush_rq(struct t3_wq *wq, struct t3_cq *cq, int count) |
363 | { | 363 | { |
364 | u32 ptr; | 364 | u32 ptr; |
365 | int flushed = 0; | ||
365 | 366 | ||
366 | PDBG("%s wq %p cq %p\n", __func__, wq, cq); | 367 | PDBG("%s wq %p cq %p\n", __func__, wq, cq); |
367 | 368 | ||
@@ -369,8 +370,11 @@ void cxio_flush_rq(struct t3_wq *wq, struct t3_cq *cq, int count) | |||
369 | PDBG("%s rq_rptr %u rq_wptr %u skip count %u\n", __func__, | 370 | PDBG("%s rq_rptr %u rq_wptr %u skip count %u\n", __func__, |
370 | wq->rq_rptr, wq->rq_wptr, count); | 371 | wq->rq_rptr, wq->rq_wptr, count); |
371 | ptr = wq->rq_rptr + count; | 372 | ptr = wq->rq_rptr + count; |
372 | while (ptr++ != wq->rq_wptr) | 373 | while (ptr++ != wq->rq_wptr) { |
373 | insert_recv_cqe(wq, cq); | 374 | insert_recv_cqe(wq, cq); |
375 | flushed++; | ||
376 | } | ||
377 | return flushed; | ||
374 | } | 378 | } |
375 | 379 | ||
376 | static void insert_sq_cqe(struct t3_wq *wq, struct t3_cq *cq, | 380 | static void insert_sq_cqe(struct t3_wq *wq, struct t3_cq *cq, |
@@ -394,9 +398,10 @@ static void insert_sq_cqe(struct t3_wq *wq, struct t3_cq *cq, | |||
394 | cq->sw_wptr++; | 398 | cq->sw_wptr++; |
395 | } | 399 | } |
396 | 400 | ||
397 | void cxio_flush_sq(struct t3_wq *wq, struct t3_cq *cq, int count) | 401 | int cxio_flush_sq(struct t3_wq *wq, struct t3_cq *cq, int count) |
398 | { | 402 | { |
399 | __u32 ptr; | 403 | __u32 ptr; |
404 | int flushed = 0; | ||
400 | struct t3_swsq *sqp = wq->sq + Q_PTR2IDX(wq->sq_rptr, wq->sq_size_log2); | 405 | struct t3_swsq *sqp = wq->sq + Q_PTR2IDX(wq->sq_rptr, wq->sq_size_log2); |
401 | 406 | ||
402 | ptr = wq->sq_rptr + count; | 407 | ptr = wq->sq_rptr + count; |
@@ -405,7 +410,9 @@ void cxio_flush_sq(struct t3_wq *wq, struct t3_cq *cq, int count) | |||
405 | insert_sq_cqe(wq, cq, sqp); | 410 | insert_sq_cqe(wq, cq, sqp); |
406 | sqp++; | 411 | sqp++; |
407 | ptr++; | 412 | ptr++; |
413 | flushed++; | ||
408 | } | 414 | } |
415 | return flushed; | ||
409 | } | 416 | } |
410 | 417 | ||
411 | /* | 418 | /* |
diff --git a/drivers/infiniband/hw/cxgb3/cxio_hal.h b/drivers/infiniband/hw/cxgb3/cxio_hal.h index 2bcff7f5046e..69ab08ebc680 100644 --- a/drivers/infiniband/hw/cxgb3/cxio_hal.h +++ b/drivers/infiniband/hw/cxgb3/cxio_hal.h | |||
@@ -173,8 +173,8 @@ u32 cxio_hal_get_pdid(struct cxio_hal_resource *rscp); | |||
173 | void cxio_hal_put_pdid(struct cxio_hal_resource *rscp, u32 pdid); | 173 | void cxio_hal_put_pdid(struct cxio_hal_resource *rscp, u32 pdid); |
174 | int __init cxio_hal_init(void); | 174 | int __init cxio_hal_init(void); |
175 | void __exit cxio_hal_exit(void); | 175 | void __exit cxio_hal_exit(void); |
176 | void cxio_flush_rq(struct t3_wq *wq, struct t3_cq *cq, int count); | 176 | int cxio_flush_rq(struct t3_wq *wq, struct t3_cq *cq, int count); |
177 | void cxio_flush_sq(struct t3_wq *wq, struct t3_cq *cq, int count); | 177 | int cxio_flush_sq(struct t3_wq *wq, struct t3_cq *cq, int count); |
178 | void cxio_count_rcqes(struct t3_cq *cq, struct t3_wq *wq, int *count); | 178 | void cxio_count_rcqes(struct t3_cq *cq, struct t3_wq *wq, int *count); |
179 | void cxio_count_scqes(struct t3_cq *cq, struct t3_wq *wq, int *count); | 179 | void cxio_count_scqes(struct t3_cq *cq, struct t3_wq *wq, int *count); |
180 | void cxio_flush_hw_cq(struct t3_cq *cq); | 180 | void cxio_flush_hw_cq(struct t3_cq *cq); |
diff --git a/drivers/infiniband/hw/cxgb3/iwch_cm.c b/drivers/infiniband/hw/cxgb3/iwch_cm.c index d44a6df9ad8c..c325c44807e8 100644 --- a/drivers/infiniband/hw/cxgb3/iwch_cm.c +++ b/drivers/infiniband/hw/cxgb3/iwch_cm.c | |||
@@ -67,10 +67,10 @@ int peer2peer = 0; | |||
67 | module_param(peer2peer, int, 0644); | 67 | module_param(peer2peer, int, 0644); |
68 | MODULE_PARM_DESC(peer2peer, "Support peer2peer ULPs (default=0)"); | 68 | MODULE_PARM_DESC(peer2peer, "Support peer2peer ULPs (default=0)"); |
69 | 69 | ||
70 | static int ep_timeout_secs = 10; | 70 | static int ep_timeout_secs = 60; |
71 | module_param(ep_timeout_secs, int, 0644); | 71 | module_param(ep_timeout_secs, int, 0644); |
72 | MODULE_PARM_DESC(ep_timeout_secs, "CM Endpoint operation timeout " | 72 | MODULE_PARM_DESC(ep_timeout_secs, "CM Endpoint operation timeout " |
73 | "in seconds (default=10)"); | 73 | "in seconds (default=60)"); |
74 | 74 | ||
75 | static int mpa_rev = 1; | 75 | static int mpa_rev = 1; |
76 | module_param(mpa_rev, int, 0644); | 76 | module_param(mpa_rev, int, 0644); |
@@ -1650,8 +1650,8 @@ static int close_con_rpl(struct t3cdev *tdev, struct sk_buff *skb, void *ctx) | |||
1650 | release = 1; | 1650 | release = 1; |
1651 | break; | 1651 | break; |
1652 | case ABORTING: | 1652 | case ABORTING: |
1653 | break; | ||
1654 | case DEAD: | 1653 | case DEAD: |
1654 | break; | ||
1655 | default: | 1655 | default: |
1656 | BUG_ON(1); | 1656 | BUG_ON(1); |
1657 | break; | 1657 | break; |
diff --git a/drivers/infiniband/hw/cxgb3/iwch_qp.c b/drivers/infiniband/hw/cxgb3/iwch_qp.c index 9b4be889c58e..79dbe5beae52 100644 --- a/drivers/infiniband/hw/cxgb3/iwch_qp.c +++ b/drivers/infiniband/hw/cxgb3/iwch_qp.c | |||
@@ -655,6 +655,7 @@ static void __flush_qp(struct iwch_qp *qhp, unsigned long *flag) | |||
655 | { | 655 | { |
656 | struct iwch_cq *rchp, *schp; | 656 | struct iwch_cq *rchp, *schp; |
657 | int count; | 657 | int count; |
658 | int flushed; | ||
658 | 659 | ||
659 | rchp = get_chp(qhp->rhp, qhp->attr.rcq); | 660 | rchp = get_chp(qhp->rhp, qhp->attr.rcq); |
660 | schp = get_chp(qhp->rhp, qhp->attr.scq); | 661 | schp = get_chp(qhp->rhp, qhp->attr.scq); |
@@ -669,20 +670,22 @@ static void __flush_qp(struct iwch_qp *qhp, unsigned long *flag) | |||
669 | spin_lock(&qhp->lock); | 670 | spin_lock(&qhp->lock); |
670 | cxio_flush_hw_cq(&rchp->cq); | 671 | cxio_flush_hw_cq(&rchp->cq); |
671 | cxio_count_rcqes(&rchp->cq, &qhp->wq, &count); | 672 | cxio_count_rcqes(&rchp->cq, &qhp->wq, &count); |
672 | cxio_flush_rq(&qhp->wq, &rchp->cq, count); | 673 | flushed = cxio_flush_rq(&qhp->wq, &rchp->cq, count); |
673 | spin_unlock(&qhp->lock); | 674 | spin_unlock(&qhp->lock); |
674 | spin_unlock_irqrestore(&rchp->lock, *flag); | 675 | spin_unlock_irqrestore(&rchp->lock, *flag); |
675 | (*rchp->ibcq.comp_handler)(&rchp->ibcq, rchp->ibcq.cq_context); | 676 | if (flushed) |
677 | (*rchp->ibcq.comp_handler)(&rchp->ibcq, rchp->ibcq.cq_context); | ||
676 | 678 | ||
677 | /* locking heirarchy: cq lock first, then qp lock. */ | 679 | /* locking heirarchy: cq lock first, then qp lock. */ |
678 | spin_lock_irqsave(&schp->lock, *flag); | 680 | spin_lock_irqsave(&schp->lock, *flag); |
679 | spin_lock(&qhp->lock); | 681 | spin_lock(&qhp->lock); |
680 | cxio_flush_hw_cq(&schp->cq); | 682 | cxio_flush_hw_cq(&schp->cq); |
681 | cxio_count_scqes(&schp->cq, &qhp->wq, &count); | 683 | cxio_count_scqes(&schp->cq, &qhp->wq, &count); |
682 | cxio_flush_sq(&qhp->wq, &schp->cq, count); | 684 | flushed = cxio_flush_sq(&qhp->wq, &schp->cq, count); |
683 | spin_unlock(&qhp->lock); | 685 | spin_unlock(&qhp->lock); |
684 | spin_unlock_irqrestore(&schp->lock, *flag); | 686 | spin_unlock_irqrestore(&schp->lock, *flag); |
685 | (*schp->ibcq.comp_handler)(&schp->ibcq, schp->ibcq.cq_context); | 687 | if (flushed) |
688 | (*schp->ibcq.comp_handler)(&schp->ibcq, schp->ibcq.cq_context); | ||
686 | 689 | ||
687 | /* deref */ | 690 | /* deref */ |
688 | if (atomic_dec_and_test(&qhp->refcnt)) | 691 | if (atomic_dec_and_test(&qhp->refcnt)) |
@@ -880,7 +883,6 @@ int iwch_modify_qp(struct iwch_dev *rhp, struct iwch_qp *qhp, | |||
880 | ep = qhp->ep; | 883 | ep = qhp->ep; |
881 | get_ep(&ep->com); | 884 | get_ep(&ep->com); |
882 | } | 885 | } |
883 | flush_qp(qhp, &flag); | ||
884 | break; | 886 | break; |
885 | case IWCH_QP_STATE_TERMINATE: | 887 | case IWCH_QP_STATE_TERMINATE: |
886 | qhp->attr.state = IWCH_QP_STATE_TERMINATE; | 888 | qhp->attr.state = IWCH_QP_STATE_TERMINATE; |
@@ -911,6 +913,7 @@ int iwch_modify_qp(struct iwch_dev *rhp, struct iwch_qp *qhp, | |||
911 | } | 913 | } |
912 | switch (attrs->next_state) { | 914 | switch (attrs->next_state) { |
913 | case IWCH_QP_STATE_IDLE: | 915 | case IWCH_QP_STATE_IDLE: |
916 | flush_qp(qhp, &flag); | ||
914 | qhp->attr.state = IWCH_QP_STATE_IDLE; | 917 | qhp->attr.state = IWCH_QP_STATE_IDLE; |
915 | qhp->attr.llp_stream_handle = NULL; | 918 | qhp->attr.llp_stream_handle = NULL; |
916 | put_ep(&qhp->ep->com); | 919 | put_ep(&qhp->ep->com); |
diff --git a/drivers/infiniband/hw/ehca/ehca_hca.c b/drivers/infiniband/hw/ehca/ehca_hca.c index 2515cbde7e65..bc3b37d2070f 100644 --- a/drivers/infiniband/hw/ehca/ehca_hca.c +++ b/drivers/infiniband/hw/ehca/ehca_hca.c | |||
@@ -101,7 +101,6 @@ int ehca_query_device(struct ib_device *ibdev, struct ib_device_attr *props) | |||
101 | props->max_ee = limit_uint(rblock->max_rd_ee_context); | 101 | props->max_ee = limit_uint(rblock->max_rd_ee_context); |
102 | props->max_rdd = limit_uint(rblock->max_rd_domain); | 102 | props->max_rdd = limit_uint(rblock->max_rd_domain); |
103 | props->max_fmr = limit_uint(rblock->max_mr); | 103 | props->max_fmr = limit_uint(rblock->max_mr); |
104 | props->local_ca_ack_delay = limit_uint(rblock->local_ca_ack_delay); | ||
105 | props->max_qp_rd_atom = limit_uint(rblock->max_rr_qp); | 104 | props->max_qp_rd_atom = limit_uint(rblock->max_rr_qp); |
106 | props->max_ee_rd_atom = limit_uint(rblock->max_rr_ee_context); | 105 | props->max_ee_rd_atom = limit_uint(rblock->max_rr_ee_context); |
107 | props->max_res_rd_atom = limit_uint(rblock->max_rr_hca); | 106 | props->max_res_rd_atom = limit_uint(rblock->max_rr_hca); |
@@ -115,7 +114,7 @@ int ehca_query_device(struct ib_device *ibdev, struct ib_device_attr *props) | |||
115 | } | 114 | } |
116 | 115 | ||
117 | props->max_pkeys = 16; | 116 | props->max_pkeys = 16; |
118 | props->local_ca_ack_delay = limit_uint(rblock->local_ca_ack_delay); | 117 | props->local_ca_ack_delay = min_t(u8, rblock->local_ca_ack_delay, 255); |
119 | props->max_raw_ipv6_qp = limit_uint(rblock->max_raw_ipv6_qp); | 118 | props->max_raw_ipv6_qp = limit_uint(rblock->max_raw_ipv6_qp); |
120 | props->max_raw_ethy_qp = limit_uint(rblock->max_raw_ethy_qp); | 119 | props->max_raw_ethy_qp = limit_uint(rblock->max_raw_ethy_qp); |
121 | props->max_mcast_grp = limit_uint(rblock->max_mcast_grp); | 120 | props->max_mcast_grp = limit_uint(rblock->max_mcast_grp); |
@@ -136,7 +135,7 @@ query_device1: | |||
136 | return ret; | 135 | return ret; |
137 | } | 136 | } |
138 | 137 | ||
139 | static int map_mtu(struct ehca_shca *shca, u32 fw_mtu) | 138 | static enum ib_mtu map_mtu(struct ehca_shca *shca, u32 fw_mtu) |
140 | { | 139 | { |
141 | switch (fw_mtu) { | 140 | switch (fw_mtu) { |
142 | case 0x1: | 141 | case 0x1: |
@@ -156,7 +155,7 @@ static int map_mtu(struct ehca_shca *shca, u32 fw_mtu) | |||
156 | } | 155 | } |
157 | } | 156 | } |
158 | 157 | ||
159 | static int map_number_of_vls(struct ehca_shca *shca, u32 vl_cap) | 158 | static u8 map_number_of_vls(struct ehca_shca *shca, u32 vl_cap) |
160 | { | 159 | { |
161 | switch (vl_cap) { | 160 | switch (vl_cap) { |
162 | case 0x1: | 161 | case 0x1: |
diff --git a/drivers/infiniband/hw/mlx4/cq.c b/drivers/infiniband/hw/mlx4/cq.c index 2f199c5c4a72..4521319b1406 100644 --- a/drivers/infiniband/hw/mlx4/cq.c +++ b/drivers/infiniband/hw/mlx4/cq.c | |||
@@ -246,7 +246,7 @@ err_mtt: | |||
246 | if (context) | 246 | if (context) |
247 | ib_umem_release(cq->umem); | 247 | ib_umem_release(cq->umem); |
248 | else | 248 | else |
249 | mlx4_ib_free_cq_buf(dev, &cq->buf, entries); | 249 | mlx4_ib_free_cq_buf(dev, &cq->buf, cq->ibcq.cqe); |
250 | 250 | ||
251 | err_db: | 251 | err_db: |
252 | if (!context) | 252 | if (!context) |
@@ -434,7 +434,7 @@ int mlx4_ib_destroy_cq(struct ib_cq *cq) | |||
434 | mlx4_ib_db_unmap_user(to_mucontext(cq->uobject->context), &mcq->db); | 434 | mlx4_ib_db_unmap_user(to_mucontext(cq->uobject->context), &mcq->db); |
435 | ib_umem_release(mcq->umem); | 435 | ib_umem_release(mcq->umem); |
436 | } else { | 436 | } else { |
437 | mlx4_ib_free_cq_buf(dev, &mcq->buf, cq->cqe + 1); | 437 | mlx4_ib_free_cq_buf(dev, &mcq->buf, cq->cqe); |
438 | mlx4_db_free(dev->dev, &mcq->db); | 438 | mlx4_db_free(dev->dev, &mcq->db); |
439 | } | 439 | } |
440 | 440 | ||
diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h index 9044f8803532..ca126fc2b853 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib.h +++ b/drivers/infiniband/ulp/ipoib/ipoib.h | |||
@@ -334,6 +334,7 @@ struct ipoib_dev_priv { | |||
334 | #endif | 334 | #endif |
335 | int hca_caps; | 335 | int hca_caps; |
336 | struct ipoib_ethtool_st ethtool; | 336 | struct ipoib_ethtool_st ethtool; |
337 | struct timer_list poll_timer; | ||
337 | }; | 338 | }; |
338 | 339 | ||
339 | struct ipoib_ah { | 340 | struct ipoib_ah { |
@@ -404,6 +405,7 @@ extern struct workqueue_struct *ipoib_workqueue; | |||
404 | 405 | ||
405 | int ipoib_poll(struct napi_struct *napi, int budget); | 406 | int ipoib_poll(struct napi_struct *napi, int budget); |
406 | void ipoib_ib_completion(struct ib_cq *cq, void *dev_ptr); | 407 | void ipoib_ib_completion(struct ib_cq *cq, void *dev_ptr); |
408 | void ipoib_send_comp_handler(struct ib_cq *cq, void *dev_ptr); | ||
407 | 409 | ||
408 | struct ipoib_ah *ipoib_create_ah(struct net_device *dev, | 410 | struct ipoib_ah *ipoib_create_ah(struct net_device *dev, |
409 | struct ib_pd *pd, struct ib_ah_attr *attr); | 411 | struct ib_pd *pd, struct ib_ah_attr *attr); |
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c index 97b815c1a3fc..f429bce24c20 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c | |||
@@ -461,6 +461,26 @@ void ipoib_ib_completion(struct ib_cq *cq, void *dev_ptr) | |||
461 | netif_rx_schedule(dev, &priv->napi); | 461 | netif_rx_schedule(dev, &priv->napi); |
462 | } | 462 | } |
463 | 463 | ||
464 | static void drain_tx_cq(struct net_device *dev) | ||
465 | { | ||
466 | struct ipoib_dev_priv *priv = netdev_priv(dev); | ||
467 | unsigned long flags; | ||
468 | |||
469 | spin_lock_irqsave(&priv->tx_lock, flags); | ||
470 | while (poll_tx(priv)) | ||
471 | ; /* nothing */ | ||
472 | |||
473 | if (netif_queue_stopped(dev)) | ||
474 | mod_timer(&priv->poll_timer, jiffies + 1); | ||
475 | |||
476 | spin_unlock_irqrestore(&priv->tx_lock, flags); | ||
477 | } | ||
478 | |||
479 | void ipoib_send_comp_handler(struct ib_cq *cq, void *dev_ptr) | ||
480 | { | ||
481 | drain_tx_cq((struct net_device *)dev_ptr); | ||
482 | } | ||
483 | |||
464 | static inline int post_send(struct ipoib_dev_priv *priv, | 484 | static inline int post_send(struct ipoib_dev_priv *priv, |
465 | unsigned int wr_id, | 485 | unsigned int wr_id, |
466 | struct ib_ah *address, u32 qpn, | 486 | struct ib_ah *address, u32 qpn, |
@@ -555,12 +575,22 @@ void ipoib_send(struct net_device *dev, struct sk_buff *skb, | |||
555 | else | 575 | else |
556 | priv->tx_wr.send_flags &= ~IB_SEND_IP_CSUM; | 576 | priv->tx_wr.send_flags &= ~IB_SEND_IP_CSUM; |
557 | 577 | ||
578 | if (++priv->tx_outstanding == ipoib_sendq_size) { | ||
579 | ipoib_dbg(priv, "TX ring full, stopping kernel net queue\n"); | ||
580 | if (ib_req_notify_cq(priv->send_cq, IB_CQ_NEXT_COMP)) | ||
581 | ipoib_warn(priv, "request notify on send CQ failed\n"); | ||
582 | netif_stop_queue(dev); | ||
583 | } | ||
584 | |||
558 | if (unlikely(post_send(priv, priv->tx_head & (ipoib_sendq_size - 1), | 585 | if (unlikely(post_send(priv, priv->tx_head & (ipoib_sendq_size - 1), |
559 | address->ah, qpn, tx_req, phead, hlen))) { | 586 | address->ah, qpn, tx_req, phead, hlen))) { |
560 | ipoib_warn(priv, "post_send failed\n"); | 587 | ipoib_warn(priv, "post_send failed\n"); |
561 | ++dev->stats.tx_errors; | 588 | ++dev->stats.tx_errors; |
589 | --priv->tx_outstanding; | ||
562 | ipoib_dma_unmap_tx(priv->ca, tx_req); | 590 | ipoib_dma_unmap_tx(priv->ca, tx_req); |
563 | dev_kfree_skb_any(skb); | 591 | dev_kfree_skb_any(skb); |
592 | if (netif_queue_stopped(dev)) | ||
593 | netif_wake_queue(dev); | ||
564 | } else { | 594 | } else { |
565 | dev->trans_start = jiffies; | 595 | dev->trans_start = jiffies; |
566 | 596 | ||
@@ -568,14 +598,11 @@ void ipoib_send(struct net_device *dev, struct sk_buff *skb, | |||
568 | ++priv->tx_head; | 598 | ++priv->tx_head; |
569 | skb_orphan(skb); | 599 | skb_orphan(skb); |
570 | 600 | ||
571 | if (++priv->tx_outstanding == ipoib_sendq_size) { | ||
572 | ipoib_dbg(priv, "TX ring full, stopping kernel net queue\n"); | ||
573 | netif_stop_queue(dev); | ||
574 | } | ||
575 | } | 601 | } |
576 | 602 | ||
577 | if (unlikely(priv->tx_outstanding > MAX_SEND_CQE)) | 603 | if (unlikely(priv->tx_outstanding > MAX_SEND_CQE)) |
578 | poll_tx(priv); | 604 | while (poll_tx(priv)) |
605 | ; /* nothing */ | ||
579 | } | 606 | } |
580 | 607 | ||
581 | static void __ipoib_reap_ah(struct net_device *dev) | 608 | static void __ipoib_reap_ah(struct net_device *dev) |
@@ -609,6 +636,11 @@ void ipoib_reap_ah(struct work_struct *work) | |||
609 | round_jiffies_relative(HZ)); | 636 | round_jiffies_relative(HZ)); |
610 | } | 637 | } |
611 | 638 | ||
639 | static void ipoib_ib_tx_timer_func(unsigned long ctx) | ||
640 | { | ||
641 | drain_tx_cq((struct net_device *)ctx); | ||
642 | } | ||
643 | |||
612 | int ipoib_ib_dev_open(struct net_device *dev) | 644 | int ipoib_ib_dev_open(struct net_device *dev) |
613 | { | 645 | { |
614 | struct ipoib_dev_priv *priv = netdev_priv(dev); | 646 | struct ipoib_dev_priv *priv = netdev_priv(dev); |
@@ -645,6 +677,10 @@ int ipoib_ib_dev_open(struct net_device *dev) | |||
645 | queue_delayed_work(ipoib_workqueue, &priv->ah_reap_task, | 677 | queue_delayed_work(ipoib_workqueue, &priv->ah_reap_task, |
646 | round_jiffies_relative(HZ)); | 678 | round_jiffies_relative(HZ)); |
647 | 679 | ||
680 | init_timer(&priv->poll_timer); | ||
681 | priv->poll_timer.function = ipoib_ib_tx_timer_func; | ||
682 | priv->poll_timer.data = (unsigned long)dev; | ||
683 | |||
648 | set_bit(IPOIB_FLAG_INITIALIZED, &priv->flags); | 684 | set_bit(IPOIB_FLAG_INITIALIZED, &priv->flags); |
649 | 685 | ||
650 | return 0; | 686 | return 0; |
@@ -810,6 +846,7 @@ int ipoib_ib_dev_stop(struct net_device *dev, int flush) | |||
810 | ipoib_dbg(priv, "All sends and receives done.\n"); | 846 | ipoib_dbg(priv, "All sends and receives done.\n"); |
811 | 847 | ||
812 | timeout: | 848 | timeout: |
849 | del_timer_sync(&priv->poll_timer); | ||
813 | qp_attr.qp_state = IB_QPS_RESET; | 850 | qp_attr.qp_state = IB_QPS_RESET; |
814 | if (ib_modify_qp(priv->qp, &qp_attr, IB_QP_STATE)) | 851 | if (ib_modify_qp(priv->qp, &qp_attr, IB_QP_STATE)) |
815 | ipoib_warn(priv, "Failed to modify QP to RESET state\n"); | 852 | ipoib_warn(priv, "Failed to modify QP to RESET state\n"); |
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_verbs.c b/drivers/infiniband/ulp/ipoib/ipoib_verbs.c index c1e7ece1fd44..8766d29ce3b7 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_verbs.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_verbs.c | |||
@@ -187,7 +187,8 @@ int ipoib_transport_dev_init(struct net_device *dev, struct ib_device *ca) | |||
187 | goto out_free_mr; | 187 | goto out_free_mr; |
188 | } | 188 | } |
189 | 189 | ||
190 | priv->send_cq = ib_create_cq(priv->ca, NULL, NULL, dev, ipoib_sendq_size, 0); | 190 | priv->send_cq = ib_create_cq(priv->ca, ipoib_send_comp_handler, NULL, |
191 | dev, ipoib_sendq_size, 0); | ||
191 | if (IS_ERR(priv->send_cq)) { | 192 | if (IS_ERR(priv->send_cq)) { |
192 | printk(KERN_WARNING "%s: failed to create send CQ\n", ca->name); | 193 | printk(KERN_WARNING "%s: failed to create send CQ\n", ca->name); |
193 | goto out_free_recv_cq; | 194 | goto out_free_recv_cq; |