Skip to content

Commit 154257f

Browse files
Ralph CampbellRoland Dreier
authored andcommitted
IB/ipath: Fix a race condition when generating ACKs
Fix a problem where simple ACKs can be sent ahead of RDMA read responses thus implicitly NAKing the RDMA read. Signed-off-by: Ralph Campbell <[email protected]> Signed-off-by: Robert Walsh <[email protected]> Signed-off-by: Roland Dreier <[email protected]>
1 parent 6ed89b9 commit 154257f

File tree

1 file changed

+15
-13
lines changed

1 file changed

+15
-13
lines changed

drivers/infiniband/hw/ipath/ipath_rc.c

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -98,13 +98,21 @@ static int ipath_make_rc_ack(struct ipath_qp *qp,
9898
case OP(RDMA_READ_RESPONSE_LAST):
9999
case OP(RDMA_READ_RESPONSE_ONLY):
100100
case OP(ATOMIC_ACKNOWLEDGE):
101-
qp->s_ack_state = OP(ACKNOWLEDGE);
101+
/*
102+
* We can increment the tail pointer now that the last
103+
* response has been sent instead of only being
104+
* constructed.
105+
*/
106+
if (++qp->s_tail_ack_queue > IPATH_MAX_RDMA_ATOMIC)
107+
qp->s_tail_ack_queue = 0;
102108
/* FALLTHROUGH */
109+
case OP(SEND_ONLY):
103110
case OP(ACKNOWLEDGE):
104111
/* Check for no next entry in the queue. */
105112
if (qp->r_head_ack_queue == qp->s_tail_ack_queue) {
106113
if (qp->s_flags & IPATH_S_ACK_PENDING)
107114
goto normal;
115+
qp->s_ack_state = OP(ACKNOWLEDGE);
108116
goto bail;
109117
}
110118

@@ -117,12 +125,8 @@ static int ipath_make_rc_ack(struct ipath_qp *qp,
117125
if (len > pmtu) {
118126
len = pmtu;
119127
qp->s_ack_state = OP(RDMA_READ_RESPONSE_FIRST);
120-
} else {
128+
} else
121129
qp->s_ack_state = OP(RDMA_READ_RESPONSE_ONLY);
122-
if (++qp->s_tail_ack_queue >
123-
IPATH_MAX_RDMA_ATOMIC)
124-
qp->s_tail_ack_queue = 0;
125-
}
126130
ohdr->u.aeth = ipath_compute_aeth(qp);
127131
hwords++;
128132
qp->s_ack_rdma_psn = e->psn;
@@ -139,8 +143,6 @@ static int ipath_make_rc_ack(struct ipath_qp *qp,
139143
cpu_to_be32(e->atomic_data);
140144
hwords += sizeof(ohdr->u.at) / sizeof(u32);
141145
bth2 = e->psn;
142-
if (++qp->s_tail_ack_queue > IPATH_MAX_RDMA_ATOMIC)
143-
qp->s_tail_ack_queue = 0;
144146
}
145147
bth0 = qp->s_ack_state << 24;
146148
break;
@@ -156,8 +158,6 @@ static int ipath_make_rc_ack(struct ipath_qp *qp,
156158
ohdr->u.aeth = ipath_compute_aeth(qp);
157159
hwords++;
158160
qp->s_ack_state = OP(RDMA_READ_RESPONSE_LAST);
159-
if (++qp->s_tail_ack_queue > IPATH_MAX_RDMA_ATOMIC)
160-
qp->s_tail_ack_queue = 0;
161161
}
162162
bth0 = qp->s_ack_state << 24;
163163
bth2 = qp->s_ack_rdma_psn++ & IPATH_PSN_MASK;
@@ -171,7 +171,7 @@ static int ipath_make_rc_ack(struct ipath_qp *qp,
171171
* the ACK before setting s_ack_state to ACKNOWLEDGE
172172
* (see above).
173173
*/
174-
qp->s_ack_state = OP(ATOMIC_ACKNOWLEDGE);
174+
qp->s_ack_state = OP(SEND_ONLY);
175175
qp->s_flags &= ~IPATH_S_ACK_PENDING;
176176
qp->s_cur_sge = NULL;
177177
if (qp->s_nak_state)
@@ -223,7 +223,7 @@ int ipath_make_rc_req(struct ipath_qp *qp,
223223
/* Sending responses has higher priority over sending requests. */
224224
if ((qp->r_head_ack_queue != qp->s_tail_ack_queue ||
225225
(qp->s_flags & IPATH_S_ACK_PENDING) ||
226-
qp->s_ack_state != IB_OPCODE_RC_ACKNOWLEDGE) &&
226+
qp->s_ack_state != OP(ACKNOWLEDGE)) &&
227227
ipath_make_rc_ack(qp, ohdr, pmtu, bth0p, bth2p))
228228
goto done;
229229

@@ -585,7 +585,9 @@ static void send_rc_ack(struct ipath_qp *qp)
585585
unsigned long flags;
586586

587587
/* Don't send ACK or NAK if a RDMA read or atomic is pending. */
588-
if (qp->r_head_ack_queue != qp->s_tail_ack_queue)
588+
if (qp->r_head_ack_queue != qp->s_tail_ack_queue ||
589+
(qp->s_flags & IPATH_S_ACK_PENDING) ||
590+
qp->s_ack_state != OP(ACKNOWLEDGE))
589591
goto queue_ack;
590592

591593
/* Construct the header. */

0 commit comments

Comments
 (0)