aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/hw/ipath
diff options
context:
space:
mode:
authorBryan O'Sullivan <bos@pathscale.com>2006-09-28 11:59:57 -0400
committerRoland Dreier <rolandd@cisco.com>2006-09-28 14:16:21 -0400
commit6022943eb4cb3cb9e43f27f1faeaba38e162d966 (patch)
tree0c495a94448610e20a4872416b85c8ffdb0f2adf /drivers/infiniband/hw/ipath
parentfd6a79a786b84510d00ee6aa6449a468e6d75dee (diff)
IB/ipath: Limit # of packets sent without an ACK received
The sender requests an ACK every 1/2 MB to avoid retransmit timeouts that were causing MVAPICH mod_bw to fail after a predictable number of sends. Signed-off-by: Bryan O'Sullivan <bryan.osullivan@qlogic.com> Signed-off-by: Roland Dreier <rolandd@cisco.com>
Diffstat (limited to 'drivers/infiniband/hw/ipath')
-rw-r--r--drivers/infiniband/hw/ipath/ipath_qp.c3
-rw-r--r--drivers/infiniband/hw/ipath/ipath_rc.c47
-rw-r--r--drivers/infiniband/hw/ipath/ipath_verbs.c3
-rw-r--r--drivers/infiniband/hw/ipath/ipath_verbs.h4
4 files changed, 37 insertions, 20 deletions
diff --git a/drivers/infiniband/hw/ipath/ipath_qp.c b/drivers/infiniband/hw/ipath/ipath_qp.c
index 224b0f40767f..ecfaca7a571b 100644
--- a/drivers/infiniband/hw/ipath/ipath_qp.c
+++ b/drivers/infiniband/hw/ipath/ipath_qp.c
@@ -342,6 +342,7 @@ static void ipath_reset_qp(struct ipath_qp *qp)
342 qp->s_last = 0; 342 qp->s_last = 0;
343 qp->s_ssn = 1; 343 qp->s_ssn = 1;
344 qp->s_lsn = 0; 344 qp->s_lsn = 0;
345 qp->s_wait_credit = 0;
345 if (qp->r_rq.wq) { 346 if (qp->r_rq.wq) {
346 qp->r_rq.wq->head = 0; 347 qp->r_rq.wq->head = 0;
347 qp->r_rq.wq->tail = 0; 348 qp->r_rq.wq->tail = 0;
@@ -516,7 +517,7 @@ int ipath_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
516 qp->remote_qpn = attr->dest_qp_num; 517 qp->remote_qpn = attr->dest_qp_num;
517 518
518 if (attr_mask & IB_QP_SQ_PSN) { 519 if (attr_mask & IB_QP_SQ_PSN) {
519 qp->s_next_psn = attr->sq_psn; 520 qp->s_psn = qp->s_next_psn = attr->sq_psn;
520 qp->s_last_psn = qp->s_next_psn - 1; 521 qp->s_last_psn = qp->s_next_psn - 1;
521 } 522 }
522 523
diff --git a/drivers/infiniband/hw/ipath/ipath_rc.c b/drivers/infiniband/hw/ipath/ipath_rc.c
index a08654042c03..52caa2edf5a4 100644
--- a/drivers/infiniband/hw/ipath/ipath_rc.c
+++ b/drivers/infiniband/hw/ipath/ipath_rc.c
@@ -201,6 +201,18 @@ int ipath_make_rc_req(struct ipath_qp *qp,
201 qp->s_rnr_timeout) 201 qp->s_rnr_timeout)
202 goto done; 202 goto done;
203 203
204 /* Limit the number of packets sent without an ACK. */
205 if (ipath_cmp24(qp->s_psn, qp->s_last_psn + IPATH_PSN_CREDIT) > 0) {
206 qp->s_wait_credit = 1;
207 dev->n_rc_stalls++;
208 spin_lock(&dev->pending_lock);
209 if (list_empty(&qp->timerwait))
210 list_add_tail(&qp->timerwait,
211 &dev->pending[dev->pending_index]);
212 spin_unlock(&dev->pending_lock);
213 goto done;
214 }
215
204 /* header size in 32-bit words LRH+BTH = (8+12)/4. */ 216 /* header size in 32-bit words LRH+BTH = (8+12)/4. */
205 hwords = 5; 217 hwords = 5;
206 bth0 = 0; 218 bth0 = 0;
@@ -221,7 +233,7 @@ int ipath_make_rc_req(struct ipath_qp *qp,
221 /* Check if send work queue is empty. */ 233 /* Check if send work queue is empty. */
222 if (qp->s_tail == qp->s_head) 234 if (qp->s_tail == qp->s_head)
223 goto done; 235 goto done;
224 qp->s_psn = wqe->psn = qp->s_next_psn; 236 wqe->psn = qp->s_next_psn;
225 newreq = 1; 237 newreq = 1;
226 } 238 }
227 /* 239 /*
@@ -393,12 +405,6 @@ int ipath_make_rc_req(struct ipath_qp *qp,
393 ss = &qp->s_sge; 405 ss = &qp->s_sge;
394 len = qp->s_len; 406 len = qp->s_len;
395 if (len > pmtu) { 407 if (len > pmtu) {
396 /*
397 * Request an ACK every 1/2 MB to avoid retransmit
398 * timeouts.
399 */
400 if (((wqe->length - len) % (512 * 1024)) == 0)
401 bth2 |= 1 << 31;
402 len = pmtu; 408 len = pmtu;
403 break; 409 break;
404 } 410 }
@@ -435,12 +441,6 @@ int ipath_make_rc_req(struct ipath_qp *qp,
435 ss = &qp->s_sge; 441 ss = &qp->s_sge;
436 len = qp->s_len; 442 len = qp->s_len;
437 if (len > pmtu) { 443 if (len > pmtu) {
438 /*
439 * Request an ACK every 1/2 MB to avoid retransmit
440 * timeouts.
441 */
442 if (((wqe->length - len) % (512 * 1024)) == 0)
443 bth2 |= 1 << 31;
444 len = pmtu; 444 len = pmtu;
445 break; 445 break;
446 } 446 }
@@ -498,6 +498,8 @@ int ipath_make_rc_req(struct ipath_qp *qp,
498 */ 498 */
499 goto done; 499 goto done;
500 } 500 }
501 if (ipath_cmp24(qp->s_psn, qp->s_last_psn + IPATH_PSN_CREDIT - 1) >= 0)
502 bth2 |= 1 << 31; /* Request ACK. */
501 qp->s_len -= len; 503 qp->s_len -= len;
502 qp->s_hdrwords = hwords; 504 qp->s_hdrwords = hwords;
503 qp->s_cur_sge = ss; 505 qp->s_cur_sge = ss;
@@ -737,6 +739,15 @@ bail:
737 return; 739 return;
738} 740}
739 741
742static inline void update_last_psn(struct ipath_qp *qp, u32 psn)
743{
744 if (qp->s_wait_credit) {
745 qp->s_wait_credit = 0;
746 tasklet_hi_schedule(&qp->s_task);
747 }
748 qp->s_last_psn = psn;
749}
750
740/** 751/**
741 * do_rc_ack - process an incoming RC ACK 752 * do_rc_ack - process an incoming RC ACK
742 * @qp: the QP the ACK came in on 753 * @qp: the QP the ACK came in on
@@ -805,7 +816,7 @@ static int do_rc_ack(struct ipath_qp *qp, u32 aeth, u32 psn, int opcode)
805 * The last valid PSN seen is the previous 816 * The last valid PSN seen is the previous
806 * request's. 817 * request's.
807 */ 818 */
808 qp->s_last_psn = wqe->psn - 1; 819 update_last_psn(qp, wqe->psn - 1);
809 /* Retry this request. */ 820 /* Retry this request. */
810 ipath_restart_rc(qp, wqe->psn, &wc); 821 ipath_restart_rc(qp, wqe->psn, &wc);
811 /* 822 /*
@@ -864,7 +875,7 @@ static int do_rc_ack(struct ipath_qp *qp, u32 aeth, u32 psn, int opcode)
864 ipath_get_credit(qp, aeth); 875 ipath_get_credit(qp, aeth);
865 qp->s_rnr_retry = qp->s_rnr_retry_cnt; 876 qp->s_rnr_retry = qp->s_rnr_retry_cnt;
866 qp->s_retry = qp->s_retry_cnt; 877 qp->s_retry = qp->s_retry_cnt;
867 qp->s_last_psn = psn; 878 update_last_psn(qp, psn);
868 ret = 1; 879 ret = 1;
869 goto bail; 880 goto bail;
870 881
@@ -883,7 +894,7 @@ static int do_rc_ack(struct ipath_qp *qp, u32 aeth, u32 psn, int opcode)
883 goto bail; 894 goto bail;
884 895
885 /* The last valid PSN is the previous PSN. */ 896 /* The last valid PSN is the previous PSN. */
886 qp->s_last_psn = psn - 1; 897 update_last_psn(qp, psn - 1);
887 898
888 dev->n_rc_resends += (int)qp->s_psn - (int)psn; 899 dev->n_rc_resends += (int)qp->s_psn - (int)psn;
889 900
@@ -898,7 +909,7 @@ static int do_rc_ack(struct ipath_qp *qp, u32 aeth, u32 psn, int opcode)
898 case 3: /* NAK */ 909 case 3: /* NAK */
899 /* The last valid PSN seen is the previous request's. */ 910 /* The last valid PSN seen is the previous request's. */
900 if (qp->s_last != qp->s_tail) 911 if (qp->s_last != qp->s_tail)
901 qp->s_last_psn = wqe->psn - 1; 912 update_last_psn(qp, wqe->psn - 1);
902 switch ((aeth >> IPATH_AETH_CREDIT_SHIFT) & 913 switch ((aeth >> IPATH_AETH_CREDIT_SHIFT) &
903 IPATH_AETH_CREDIT_MASK) { 914 IPATH_AETH_CREDIT_MASK) {
904 case 0: /* PSN sequence error */ 915 case 0: /* PSN sequence error */
@@ -1071,7 +1082,7 @@ static inline void ipath_rc_rcv_resp(struct ipath_ibdev *dev,
1071 * since we don't want s_sge modified. 1082 * since we don't want s_sge modified.
1072 */ 1083 */
1073 qp->s_len -= pmtu; 1084 qp->s_len -= pmtu;
1074 qp->s_last_psn = psn; 1085 update_last_psn(qp, psn);
1075 spin_unlock_irqrestore(&qp->s_lock, flags); 1086 spin_unlock_irqrestore(&qp->s_lock, flags);
1076 ipath_copy_sge(&qp->s_sge, data, pmtu); 1087 ipath_copy_sge(&qp->s_sge, data, pmtu);
1077 goto bail; 1088 goto bail;
diff --git a/drivers/infiniband/hw/ipath/ipath_verbs.c b/drivers/infiniband/hw/ipath/ipath_verbs.c
index b8381c5e72bd..a4bf870c5e31 100644
--- a/drivers/infiniband/hw/ipath/ipath_verbs.c
+++ b/drivers/infiniband/hw/ipath/ipath_verbs.c
@@ -1683,6 +1683,7 @@ static ssize_t show_stats(struct class_device *cdev, char *buf)
1683 "RC OTH NAKs %d\n" 1683 "RC OTH NAKs %d\n"
1684 "RC timeouts %d\n" 1684 "RC timeouts %d\n"
1685 "RC RDMA dup %d\n" 1685 "RC RDMA dup %d\n"
1686 "RC stalls %d\n"
1686 "piobuf wait %d\n" 1687 "piobuf wait %d\n"
1687 "no piobuf %d\n" 1688 "no piobuf %d\n"
1688 "PKT drops %d\n" 1689 "PKT drops %d\n"
@@ -1690,7 +1691,7 @@ static ssize_t show_stats(struct class_device *cdev, char *buf)
1690 dev->n_rc_resends, dev->n_rc_qacks, dev->n_rc_acks, 1691 dev->n_rc_resends, dev->n_rc_qacks, dev->n_rc_acks,
1691 dev->n_seq_naks, dev->n_rdma_seq, dev->n_rnr_naks, 1692 dev->n_seq_naks, dev->n_rdma_seq, dev->n_rnr_naks,
1692 dev->n_other_naks, dev->n_timeouts, 1693 dev->n_other_naks, dev->n_timeouts,
1693 dev->n_rdma_dup_busy, dev->n_piowait, 1694 dev->n_rdma_dup_busy, dev->n_rc_stalls, dev->n_piowait,
1694 dev->n_no_piobuf, dev->n_pkt_drops, dev->n_wqe_errs); 1695 dev->n_no_piobuf, dev->n_pkt_drops, dev->n_wqe_errs);
1695 for (i = 0; i < ARRAY_SIZE(dev->opstats); i++) { 1696 for (i = 0; i < ARRAY_SIZE(dev->opstats); i++) {
1696 const struct ipath_opcode_stats *si = &dev->opstats[i]; 1697 const struct ipath_opcode_stats *si = &dev->opstats[i];
diff --git a/drivers/infiniband/hw/ipath/ipath_verbs.h b/drivers/infiniband/hw/ipath/ipath_verbs.h
index 09bbb3f9a217..3fffaa02e669 100644
--- a/drivers/infiniband/hw/ipath/ipath_verbs.h
+++ b/drivers/infiniband/hw/ipath/ipath_verbs.h
@@ -370,6 +370,7 @@ struct ipath_qp {
370 u8 s_rnr_retry_cnt; 370 u8 s_rnr_retry_cnt;
371 u8 s_retry; /* requester retry counter */ 371 u8 s_retry; /* requester retry counter */
372 u8 s_rnr_retry; /* requester RNR retry counter */ 372 u8 s_rnr_retry; /* requester RNR retry counter */
373 u8 s_wait_credit; /* limit number of unacked packets sent */
373 u8 s_pkey_index; /* PKEY index to use */ 374 u8 s_pkey_index; /* PKEY index to use */
374 u8 timeout; /* Timeout for this QP */ 375 u8 timeout; /* Timeout for this QP */
375 enum ib_mtu path_mtu; 376 enum ib_mtu path_mtu;
@@ -393,6 +394,8 @@ struct ipath_qp {
393#define IPATH_S_BUSY 0 394#define IPATH_S_BUSY 0
394#define IPATH_S_SIGNAL_REQ_WR 1 395#define IPATH_S_SIGNAL_REQ_WR 1
395 396
397#define IPATH_PSN_CREDIT 2048
398
396/* 399/*
397 * Since struct ipath_swqe is not a fixed size, we can't simply index into 400 * Since struct ipath_swqe is not a fixed size, we can't simply index into
398 * struct ipath_qp.s_wq. This function does the array index computation. 401 * struct ipath_qp.s_wq. This function does the array index computation.
@@ -521,6 +524,7 @@ struct ipath_ibdev {
521 u32 n_rnr_naks; 524 u32 n_rnr_naks;
522 u32 n_other_naks; 525 u32 n_other_naks;
523 u32 n_timeouts; 526 u32 n_timeouts;
527 u32 n_rc_stalls;
524 u32 n_pkt_drops; 528 u32 n_pkt_drops;
525 u32 n_vl15_dropped; 529 u32 n_vl15_dropped;
526 u32 n_wqe_errs; 530 u32 n_wqe_errs;