aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/hw/ipath/ipath_rc.c
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/ipath_rc.c
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/ipath_rc.c')
-rw-r--r--drivers/infiniband/hw/ipath/ipath_rc.c47
1 files changed, 29 insertions, 18 deletions
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;