IB/hfi1: Add a function to build TID RDMA ACK packet

This patch adds a function to build TID RDMA ACJ packet, which is also
in the KDETH PSN space for packet ordering. This packet is used to
acknowledge the receiving of all the TID RDMA WRITE DATA packets
before the given KDETH PSN. Similar to RC ACK packets, TID RDMA ACK
packets could also be coalesced.

Signed-off-by: Mitko Haralanov <mitko.haralanov@intel.com>
Signed-off-by: Mike Marciniszyn <mike.marciniszyn@intel.com>
Signed-off-by: Ashutosh Dixit <ashutosh.dixit@intel.com>
Signed-off-by: Kaike Wan <kaike.wan@intel.com>
Signed-off-by: Dennis Dalessandro <dennis.dalessandro@intel.com>
Signed-off-by: Doug Ledford <dledford@redhat.com>
This commit is contained in:
Kaike Wan 2019-01-23 21:50:03 -08:00 committed by Doug Ledford
parent d72fe7d500
commit 0f75e325aa
3 changed files with 83 additions and 0 deletions

View File

@ -4241,3 +4241,80 @@ send_nak:
}
goto done;
}
static bool hfi1_tid_rdma_is_resync_psn(u32 psn)
{
return (bool)((psn & HFI1_KDETH_BTH_SEQ_MASK) ==
HFI1_KDETH_BTH_SEQ_MASK);
}
u32 hfi1_build_tid_rdma_write_ack(struct rvt_qp *qp, struct rvt_ack_entry *e,
struct ib_other_headers *ohdr, u16 iflow,
u32 *bth1, u32 *bth2)
{
struct hfi1_qp_priv *qpriv = qp->priv;
struct tid_flow_state *fs = &qpriv->flow_state;
struct tid_rdma_request *req = ack_to_tid_req(e);
struct tid_rdma_flow *flow = &req->flows[iflow];
struct tid_rdma_params *remote;
rcu_read_lock();
remote = rcu_dereference(qpriv->tid_rdma.remote);
KDETH_RESET(ohdr->u.tid_rdma.ack.kdeth1, JKEY, remote->jkey);
ohdr->u.tid_rdma.ack.verbs_qp = cpu_to_be32(qp->remote_qpn);
*bth1 = remote->qp;
rcu_read_unlock();
if (qpriv->resync) {
*bth2 = mask_psn((fs->generation <<
HFI1_KDETH_BTH_SEQ_SHIFT) - 1);
ohdr->u.tid_rdma.ack.aeth = rvt_compute_aeth(qp);
} else if (qpriv->s_nak_state) {
*bth2 = mask_psn(qpriv->s_nak_psn);
ohdr->u.tid_rdma.ack.aeth =
cpu_to_be32((qp->r_msn & IB_MSN_MASK) |
(qpriv->s_nak_state <<
IB_AETH_CREDIT_SHIFT));
} else {
*bth2 = full_flow_psn(flow, flow->flow_state.lpsn);
ohdr->u.tid_rdma.ack.aeth = rvt_compute_aeth(qp);
}
KDETH_RESET(ohdr->u.tid_rdma.ack.kdeth0, KVER, 0x1);
ohdr->u.tid_rdma.ack.tid_flow_qp =
cpu_to_be32(qpriv->tid_rdma.local.qp |
((flow->idx & TID_RDMA_DESTQP_FLOW_MASK) <<
TID_RDMA_DESTQP_FLOW_SHIFT) |
qpriv->rcd->ctxt);
ohdr->u.tid_rdma.ack.tid_flow_psn = 0;
ohdr->u.tid_rdma.ack.verbs_psn =
cpu_to_be32(flow->flow_state.resp_ib_psn);
if (qpriv->resync) {
/*
* If the PSN before the current expect KDETH PSN is the
* RESYNC PSN, then we never received a good TID RDMA WRITE
* DATA packet after a previous RESYNC.
* In this case, the next expected KDETH PSN stays the same.
*/
if (hfi1_tid_rdma_is_resync_psn(qpriv->r_next_psn_kdeth - 1)) {
ohdr->u.tid_rdma.ack.tid_flow_psn =
cpu_to_be32(qpriv->r_next_psn_kdeth_save);
} else {
/*
* Because the KDETH PSNs jump during a RESYNC, it's
* not possible to infer (or compute) the previous value
* of r_next_psn_kdeth in the case of back-to-back
* RESYNC packets. Therefore, we save it.
*/
qpriv->r_next_psn_kdeth_save =
qpriv->r_next_psn_kdeth - 1;
ohdr->u.tid_rdma.ack.tid_flow_psn =
cpu_to_be32(qpriv->r_next_psn_kdeth_save);
qpriv->r_next_psn_kdeth = mask_psn(*bth2 + 1);
}
qpriv->resync = false;
}
return sizeof(ohdr->u.tid_rdma.ack) / sizeof(u32);
}

View File

@ -281,4 +281,8 @@ bool hfi1_build_tid_rdma_packet(struct rvt_swqe *wqe,
void hfi1_rc_rcv_tid_rdma_write_data(struct hfi1_packet *packet);
u32 hfi1_build_tid_rdma_write_ack(struct rvt_qp *qp, struct rvt_ack_entry *e,
struct ib_other_headers *ohdr, u16 iflow,
u32 *bth1, u32 *bth2);
#endif /* HFI1_TID_RDMA_H */

View File

@ -196,7 +196,9 @@ struct hfi1_qp_priv {
u8 timeout_shift; /* account for number of packets per segment */
u32 r_next_psn_kdeth;
u32 r_next_psn_kdeth_save;
u8 sync_pt; /* Set when QP reaches sync point */
u8 resync;
};
#define HFI1_QP_WQE_INVALID ((u32)-1)