Skip to content

Commit 9e93e96

Browse files
kwan-intcdledford
authored andcommitted
IB/hfi1: Add a function to receive TID RDMA ACK packet
This patch adds a function to receive TID RDMA ACK packet, which could be an acknowledge to either a TID RDMA WRITE DATA packet or an TID RDMA RESYNC packet. For an ACK to TID RDMA WRITE DATA packet, the request segments are completed appropriately. For an ACK to a TID RDMA RESYNC packet, any pending segment flow information is updated accordingly. Signed-off-by: Mitko Haralanov <[email protected]> Signed-off-by: Mike Marciniszyn <[email protected]> Signed-off-by: Ashutosh Dixit <[email protected]> Signed-off-by: Kaike Wan <[email protected]> Signed-off-by: Dennis Dalessandro <[email protected]> Signed-off-by: Doug Ledford <[email protected]>
1 parent 0f75e32 commit 9e93e96

File tree

6 files changed

+228
-1
lines changed

6 files changed

+228
-1
lines changed

drivers/infiniband/hw/hfi1/opfn.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,9 @@ void opfn_qp_init(struct rvt_qp *qp, struct ib_qp_attr *attr, int attr_mask)
245245
struct hfi1_qp_priv *priv = qp->priv;
246246
unsigned long flags;
247247

248+
if (attr_mask & IB_QP_RETRY_CNT)
249+
priv->s_retry = attr->retry_cnt;
250+
248251
spin_lock_irqsave(&priv->opfn.lock, flags);
249252
if (ibqp->qp_type == IB_QPT_RC && HFI1_CAP_IS_KSET(TID_RDMA)) {
250253
struct tid_rdma_params *local = &priv->tid_rdma.local;

drivers/infiniband/hw/hfi1/qp.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,13 +65,15 @@ extern const struct rvt_operation_params hfi1_post_parms[];
6565
* HFI1_S_WAIT_PIO_DRAIN - qp waiting for PIOs to drain
6666
* HFI1_S_WAIT_TID_SPACE - a QP is waiting for TID resource
6767
* HFI1_S_WAIT_TID_RESP - waiting for a TID RDMA WRITE response
68+
* HFI1_S_WAIT_HALT - halt the first leg send engine
6869
* HFI1_S_MIN_BIT_MASK - the lowest bit that can be used by hfi1
6970
*/
7071
#define HFI1_S_AHG_VALID 0x80000000
7172
#define HFI1_S_AHG_CLEAR 0x40000000
7273
#define HFI1_S_WAIT_PIO_DRAIN 0x20000000
7374
#define HFI1_S_WAIT_TID_SPACE 0x10000000
7475
#define HFI1_S_WAIT_TID_RESP 0x08000000
76+
#define HFI1_S_WAIT_HALT 0x04000000
7577
#define HFI1_S_MIN_BIT_MASK 0x01000000
7678

7779
/*

drivers/infiniband/hw/hfi1/tid_rdma.c

Lines changed: 212 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,7 @@ int hfi1_qp_priv_init(struct rvt_dev_info *rdi, struct rvt_qp *qp,
319319
qpriv->flow_state.index = RXE_NUM_TID_FLOWS;
320320
qpriv->flow_state.last_index = RXE_NUM_TID_FLOWS;
321321
qpriv->flow_state.generation = KERN_GENERATION_RESERVED;
322+
qpriv->s_state = TID_OP(WRITE_RESP);
322323
qpriv->s_tid_cur = HFI1_QP_WQE_INVALID;
323324
qpriv->s_tid_head = HFI1_QP_WQE_INVALID;
324325
qpriv->s_tid_tail = HFI1_QP_WQE_INVALID;
@@ -327,6 +328,7 @@ int hfi1_qp_priv_init(struct rvt_dev_info *rdi, struct rvt_qp *qp,
327328
qpriv->r_tid_tail = HFI1_QP_WQE_INVALID;
328329
qpriv->r_tid_ack = HFI1_QP_WQE_INVALID;
329330
qpriv->r_tid_alloc = HFI1_QP_WQE_INVALID;
331+
atomic_set(&qpriv->n_tid_requests, 0);
330332
timer_setup(&qpriv->s_tid_timer, hfi1_tid_timeout, 0);
331333
INIT_LIST_HEAD(&qpriv->tid_wait);
332334

@@ -4318,3 +4320,213 @@ u32 hfi1_build_tid_rdma_write_ack(struct rvt_qp *qp, struct rvt_ack_entry *e,
43184320

43194321
return sizeof(ohdr->u.tid_rdma.ack) / sizeof(u32);
43204322
}
4323+
4324+
void hfi1_rc_rcv_tid_rdma_ack(struct hfi1_packet *packet)
4325+
{
4326+
struct ib_other_headers *ohdr = packet->ohdr;
4327+
struct rvt_qp *qp = packet->qp;
4328+
struct hfi1_qp_priv *qpriv = qp->priv;
4329+
struct rvt_swqe *wqe;
4330+
struct tid_rdma_request *req;
4331+
struct tid_rdma_flow *flow;
4332+
u32 aeth, psn, req_psn, ack_psn, fspsn, resync_psn, ack_kpsn;
4333+
bool is_fecn;
4334+
unsigned long flags;
4335+
u16 fidx;
4336+
4337+
is_fecn = process_ecn(qp, packet);
4338+
psn = mask_psn(be32_to_cpu(ohdr->bth[2]));
4339+
aeth = be32_to_cpu(ohdr->u.tid_rdma.ack.aeth);
4340+
req_psn = mask_psn(be32_to_cpu(ohdr->u.tid_rdma.ack.verbs_psn));
4341+
resync_psn = mask_psn(be32_to_cpu(ohdr->u.tid_rdma.ack.tid_flow_psn));
4342+
4343+
spin_lock_irqsave(&qp->s_lock, flags);
4344+
4345+
/* If we are waiting for an ACK to RESYNC, drop any other packets */
4346+
if ((qp->s_flags & HFI1_S_WAIT_HALT) &&
4347+
cmp_psn(psn, qpriv->s_resync_psn))
4348+
goto ack_op_err;
4349+
4350+
ack_psn = req_psn;
4351+
if (hfi1_tid_rdma_is_resync_psn(psn))
4352+
ack_kpsn = resync_psn;
4353+
else
4354+
ack_kpsn = psn;
4355+
if (aeth >> 29) {
4356+
ack_psn--;
4357+
ack_kpsn--;
4358+
}
4359+
4360+
wqe = rvt_get_swqe_ptr(qp, qp->s_acked);
4361+
4362+
if (wqe->wr.opcode != IB_WR_TID_RDMA_WRITE)
4363+
goto ack_op_err;
4364+
4365+
req = wqe_to_tid_req(wqe);
4366+
flow = &req->flows[req->acked_tail];
4367+
4368+
/* Drop stale ACK/NAK */
4369+
if (cmp_psn(psn, full_flow_psn(flow, flow->flow_state.spsn)) < 0)
4370+
goto ack_op_err;
4371+
4372+
while (cmp_psn(ack_kpsn,
4373+
full_flow_psn(flow, flow->flow_state.lpsn)) >= 0 &&
4374+
req->ack_seg < req->cur_seg) {
4375+
req->ack_seg++;
4376+
/* advance acked segment pointer */
4377+
req->acked_tail = CIRC_NEXT(req->acked_tail, MAX_FLOWS);
4378+
req->r_last_acked = flow->flow_state.resp_ib_psn;
4379+
if (req->ack_seg == req->total_segs) {
4380+
req->state = TID_REQUEST_COMPLETE;
4381+
wqe = do_rc_completion(qp, wqe,
4382+
to_iport(qp->ibqp.device,
4383+
qp->port_num));
4384+
atomic_dec(&qpriv->n_tid_requests);
4385+
if (qp->s_acked == qp->s_tail)
4386+
break;
4387+
if (wqe->wr.opcode != IB_WR_TID_RDMA_WRITE)
4388+
break;
4389+
req = wqe_to_tid_req(wqe);
4390+
}
4391+
flow = &req->flows[req->acked_tail];
4392+
}
4393+
4394+
switch (aeth >> 29) {
4395+
case 0: /* ACK */
4396+
if (qpriv->s_flags & RVT_S_WAIT_ACK)
4397+
qpriv->s_flags &= ~RVT_S_WAIT_ACK;
4398+
if (!hfi1_tid_rdma_is_resync_psn(psn)) {
4399+
hfi1_schedule_send(qp);
4400+
} else {
4401+
u32 spsn, fpsn, last_acked, generation;
4402+
struct tid_rdma_request *rptr;
4403+
4404+
/* Allow new requests (see hfi1_make_tid_rdma_pkt) */
4405+
qp->s_flags &= ~HFI1_S_WAIT_HALT;
4406+
/*
4407+
* Clear RVT_S_SEND_ONE flag in case that the TID RDMA
4408+
* ACK is received after the TID retry timer is fired
4409+
* again. In this case, do not send any more TID
4410+
* RESYNC request or wait for any more TID ACK packet.
4411+
*/
4412+
qpriv->s_flags &= ~RVT_S_SEND_ONE;
4413+
hfi1_schedule_send(qp);
4414+
4415+
if ((qp->s_acked == qpriv->s_tid_tail &&
4416+
req->ack_seg == req->total_segs) ||
4417+
qp->s_acked == qp->s_tail) {
4418+
qpriv->s_state = TID_OP(WRITE_DATA_LAST);
4419+
goto done;
4420+
}
4421+
4422+
if (req->ack_seg == req->comp_seg) {
4423+
qpriv->s_state = TID_OP(WRITE_DATA);
4424+
goto done;
4425+
}
4426+
4427+
/*
4428+
* The PSN to start with is the next PSN after the
4429+
* RESYNC PSN.
4430+
*/
4431+
psn = mask_psn(psn + 1);
4432+
generation = psn >> HFI1_KDETH_BTH_SEQ_SHIFT;
4433+
spsn = 0;
4434+
4435+
/*
4436+
* Update to the correct WQE when we get an ACK(RESYNC)
4437+
* in the middle of a request.
4438+
*/
4439+
if (delta_psn(ack_psn, wqe->lpsn))
4440+
wqe = rvt_get_swqe_ptr(qp, qp->s_acked);
4441+
req = wqe_to_tid_req(wqe);
4442+
flow = &req->flows[req->acked_tail];
4443+
/*
4444+
* RESYNC re-numbers the PSN ranges of all remaining
4445+
* segments. Also, PSN's start from 0 in the middle of a
4446+
* segment and the first segment size is less than the
4447+
* default number of packets. flow->resync_npkts is used
4448+
* to track the number of packets from the start of the
4449+
* real segment to the point of 0 PSN after the RESYNC
4450+
* in order to later correctly rewind the SGE.
4451+
*/
4452+
fpsn = full_flow_psn(flow, flow->flow_state.spsn);
4453+
req->r_ack_psn = psn;
4454+
flow->resync_npkts +=
4455+
delta_psn(mask_psn(resync_psn + 1), fpsn);
4456+
/*
4457+
* Renumber all packet sequence number ranges
4458+
* based on the new generation.
4459+
*/
4460+
last_acked = qp->s_acked;
4461+
rptr = req;
4462+
while (1) {
4463+
/* start from last acked segment */
4464+
for (fidx = rptr->acked_tail;
4465+
CIRC_CNT(rptr->setup_head, fidx,
4466+
MAX_FLOWS);
4467+
fidx = CIRC_NEXT(fidx, MAX_FLOWS)) {
4468+
u32 lpsn;
4469+
u32 gen;
4470+
4471+
flow = &rptr->flows[fidx];
4472+
gen = flow->flow_state.generation;
4473+
if (WARN_ON(gen == generation &&
4474+
flow->flow_state.spsn !=
4475+
spsn))
4476+
continue;
4477+
lpsn = flow->flow_state.lpsn;
4478+
lpsn = full_flow_psn(flow, lpsn);
4479+
flow->npkts =
4480+
delta_psn(lpsn,
4481+
mask_psn(resync_psn)
4482+
);
4483+
flow->flow_state.generation =
4484+
generation;
4485+
flow->flow_state.spsn = spsn;
4486+
flow->flow_state.lpsn =
4487+
flow->flow_state.spsn +
4488+
flow->npkts - 1;
4489+
flow->pkt = 0;
4490+
spsn += flow->npkts;
4491+
resync_psn += flow->npkts;
4492+
}
4493+
if (++last_acked == qpriv->s_tid_cur + 1)
4494+
break;
4495+
if (last_acked == qp->s_size)
4496+
last_acked = 0;
4497+
wqe = rvt_get_swqe_ptr(qp, last_acked);
4498+
rptr = wqe_to_tid_req(wqe);
4499+
}
4500+
req->cur_seg = req->ack_seg;
4501+
qpriv->s_tid_tail = qp->s_acked;
4502+
qpriv->s_state = TID_OP(WRITE_REQ);
4503+
}
4504+
done:
4505+
qpriv->s_retry = qp->s_retry_cnt;
4506+
break;
4507+
4508+
case 3: /* NAK */
4509+
switch ((aeth >> IB_AETH_CREDIT_SHIFT) &
4510+
IB_AETH_CREDIT_MASK) {
4511+
case 0: /* PSN sequence error */
4512+
flow = &req->flows[req->acked_tail];
4513+
fspsn = full_flow_psn(flow, flow->flow_state.spsn);
4514+
req->r_ack_psn = mask_psn(be32_to_cpu(ohdr->bth[2]));
4515+
req->cur_seg = req->ack_seg;
4516+
qpriv->s_tid_tail = qp->s_acked;
4517+
qpriv->s_state = TID_OP(WRITE_REQ);
4518+
qpriv->s_retry = qp->s_retry_cnt;
4519+
break;
4520+
4521+
default:
4522+
break;
4523+
}
4524+
break;
4525+
4526+
default:
4527+
break;
4528+
}
4529+
4530+
ack_op_err:
4531+
spin_unlock_irqrestore(&qp->s_lock, flags);
4532+
}

drivers/infiniband/hw/hfi1/tid_rdma.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ struct tid_rdma_request {
101101

102102
u32 seg_len;
103103
u32 total_len;
104+
u32 r_ack_psn; /* next expected ack PSN */
104105
u32 r_flow_psn; /* IB PSN of next segment start */
105106
u32 r_last_acked; /* IB PSN of last ACK'ed packet */
106107
u32 s_next_psn; /* IB PSN of next segment start for read */
@@ -285,4 +286,6 @@ u32 hfi1_build_tid_rdma_write_ack(struct rvt_qp *qp, struct rvt_ack_entry *e,
285286
struct ib_other_headers *ohdr, u16 iflow,
286287
u32 *bth1, u32 *bth2);
287288

289+
void hfi1_rc_rcv_tid_rdma_ack(struct hfi1_packet *packet);
290+
288291
#endif /* HFI1_TID_RDMA_H */

drivers/infiniband/hw/hfi1/trace_tid.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ u16 hfi1_trace_get_tid_idx(u32 ent);
5252
#define TID_READ_SENDER_PRN "[%s] qpn 0x%x newreq %u tid_r_reqs %u " \
5353
"tid_r_comp %u pending_tid_r_segs %u " \
5454
"s_flags 0x%x ps_flags 0x%x iow_flags 0x%lx " \
55-
"hw_flow_index %u generation 0x%x " \
55+
"s_state 0x%x hw_flow_index %u generation 0x%x " \
5656
"fpsn 0x%x flow_flags 0x%x"
5757

5858
#define TID_REQ_PRN "[%s] qpn 0x%x newreq %u opcode 0x%x psn 0x%x lpsn 0x%x " \
@@ -844,6 +844,7 @@ DECLARE_EVENT_CLASS(/* tid_read_sender */
844844
__field(u32, s_flags)
845845
__field(u32, ps_flags)
846846
__field(unsigned long, iow_flags)
847+
__field(u8, s_state)
847848
__field(u32, hw_flow_index)
848849
__field(u32, generation)
849850
__field(u32, fpsn)
@@ -861,6 +862,7 @@ DECLARE_EVENT_CLASS(/* tid_read_sender */
861862
__entry->s_flags = qp->s_flags;
862863
__entry->ps_flags = priv->s_flags;
863864
__entry->iow_flags = priv->s_iowait.flags;
865+
__entry->s_state = priv->s_state;
864866
__entry->hw_flow_index = priv->flow_state.index;
865867
__entry->generation = priv->flow_state.generation;
866868
__entry->fpsn = priv->flow_state.psn;
@@ -877,6 +879,7 @@ DECLARE_EVENT_CLASS(/* tid_read_sender */
877879
__entry->s_flags,
878880
__entry->ps_flags,
879881
__entry->iow_flags,
882+
__entry->s_state,
880883
__entry->hw_flow_index,
881884
__entry->generation,
882885
__entry->fpsn,

drivers/infiniband/hw/hfi1/verbs.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,9 +170,12 @@ struct hfi1_qp_priv {
170170
struct tid_rdma_qp_params tid_rdma;
171171
struct rvt_qp *owner;
172172
u8 hdr_type; /* 9B or 16B */
173+
atomic_t n_tid_requests; /* # of sent TID RDMA requests */
173174
unsigned long tid_timer_timeout_jiffies;
174175

175176
/* variables for the TID RDMA SE state machine */
177+
u8 s_state;
178+
u8 s_retry;
176179
u8 rnr_nak_state; /* RNR NAK state */
177180
u8 s_nak_state;
178181
u32 s_nak_psn;
@@ -197,6 +200,7 @@ struct hfi1_qp_priv {
197200

198201
u32 r_next_psn_kdeth;
199202
u32 r_next_psn_kdeth_save;
203+
u32 s_resync_psn;
200204
u8 sync_pt; /* Set when QP reaches sync point */
201205
u8 resync;
202206
};

0 commit comments

Comments
 (0)