in prov/gni/src/gnix_rma.c [715:892]
int _gnix_rma_post_rdma_chain_req(void *data)
{
struct gnix_fab_req *req = (struct gnix_fab_req *)data;
struct gnix_fid_ep *ep = req->gnix_ep;
struct gnix_nic *nic = ep->nic;
struct gnix_tx_descriptor *bte_txd, *ct_txd;
gni_mem_handle_t mdh;
gni_return_t status;
int rc;
int inject_err = _gnix_req_inject_err(req);
int head_off, head_len, tail_len;
int fma_chain = 0;
if (req->int_tx_buf_e == NULL) {
req->int_tx_buf_e = _gnix_ep_get_int_tx_buf(ep);
if (req->int_tx_buf_e == NULL) {
GNIX_WARN(FI_LOG_EP_DATA, "RAN OUT OF INT_TX_BUFS");
return -FI_ENOSPC;
}
}
req->int_tx_buf = ((struct gnix_int_tx_buf *) req->int_tx_buf_e)->buf;
req->int_tx_mdh = _gnix_ep_get_int_tx_mdh(req->int_tx_buf_e);
if (!gnix_ops_allowed(ep, req->vc->peer_caps, req->flags)) {
rc = __gnix_rma_post_err_no_retrans(req, FI_EOPNOTSUPP);
if (rc != FI_SUCCESS)
GNIX_WARN(FI_LOG_EP_DATA,
"__gnix_rma_post_err_no_retrans() failed: %d\n",
rc);
return -FI_ECANCELED;
}
rc = _gnix_nic_tx_alloc(nic, &bte_txd);
if (rc) {
GNIX_INFO(FI_LOG_EP_DATA,
"BTE _gnix_nic_tx_alloc() failed: %d\n",
rc);
return -FI_ENOSPC;
}
rc = _gnix_nic_tx_alloc(nic, &ct_txd);
if (rc) {
_gnix_nic_tx_free(nic, bte_txd);
GNIX_INFO(FI_LOG_EP_DATA,
"CT _gnix_nic_tx_alloc() failed: %d\n",
rc);
return -FI_ENOSPC;
}
_GNIX_CONVERT_MR_KEY(ep->auth_key->using_vmdh,
req->vc->peer_key_offset,
_gnix_convert_key_to_mhdl,
&req->rma.rem_mr_key, &mdh);
/* BTE TXD */
bte_txd->completer_fn = __gnix_rma_txd_complete;
bte_txd->req = req;
bte_txd->gni_desc.type = GNI_POST_RDMA_GET;
bte_txd->gni_desc.cq_mode = GNI_CQMODE_GLOBAL_EVENT; /* check flags */
bte_txd->gni_desc.dlvr_mode = GNI_DLVMODE_PERFORMANCE; /* check flags */
head_off = req->rma.rem_addr & GNI_READ_ALIGN_MASK;
head_len = head_off ? GNI_READ_ALIGN - head_off : 0;
tail_len = (req->rma.rem_addr + req->rma.len) & GNI_READ_ALIGN_MASK;
bte_txd->gni_desc.local_addr = (uint64_t)req->rma.loc_addr + head_len;
bte_txd->gni_desc.remote_addr = (uint64_t)req->rma.rem_addr + head_len;
bte_txd->gni_desc.length = req->rma.len - head_len - tail_len;
bte_txd->gni_desc.remote_mem_hndl = mdh;
bte_txd->gni_desc.rdma_mode = 0; /* check flags */
bte_txd->gni_desc.src_cq_hndl = nic->tx_cq; /* check flags */
bte_txd->gni_desc.local_mem_hndl = req->rma.loc_md->mem_hndl;
GNIX_LOG_DUMP_TXD(bte_txd);
/* FMA TXD */
ct_txd->completer_fn = __gnix_rma_txd_complete;
ct_txd->req = req;
ct_txd->gni_desc.type = GNI_POST_FMA_GET;
ct_txd->gni_desc.cq_mode = GNI_CQMODE_GLOBAL_EVENT; /* check flags */
ct_txd->gni_desc.dlvr_mode = GNI_DLVMODE_PERFORMANCE; /* check flags */
ct_txd->gni_desc.remote_mem_hndl = mdh;
ct_txd->gni_desc.rdma_mode = 0; /* check flags */
ct_txd->gni_desc.src_cq_hndl = nic->tx_cq; /* check flags */
ct_txd->gni_desc.local_mem_hndl = req->int_tx_mdh;
ct_txd->gni_desc.length = GNI_READ_ALIGN;
if (head_off) {
ct_txd->gni_desc.remote_addr =
req->rma.rem_addr & ~GNI_READ_ALIGN_MASK;
ct_txd->gni_desc.local_addr = (uint64_t)req->int_tx_buf;
if (tail_len) {
ct_txd->gni_desc.next_descr = &ct_txd->gni_ct_descs[0];
ct_txd->gni_ct_descs[0].ep_hndl = req->vc->gni_ep;
ct_txd->gni_ct_descs[0].length = GNI_READ_ALIGN;
ct_txd->gni_ct_descs[0].remote_addr =
(req->rma.rem_addr +
req->rma.len) & ~GNI_READ_ALIGN_MASK;
ct_txd->gni_ct_descs[0].remote_mem_hndl = mdh;
ct_txd->gni_ct_descs[0].local_addr =
(uint64_t)req->int_tx_buf +
GNI_READ_ALIGN;
ct_txd->gni_ct_descs[0].local_mem_hndl =
req->int_tx_mdh;
ct_txd->gni_ct_descs[0].next_descr = NULL;
fma_chain = 1;
}
} else {
ct_txd->gni_desc.remote_addr =
(req->rma.rem_addr +
req->rma.len) & ~GNI_READ_ALIGN_MASK;
ct_txd->gni_desc.local_addr =
(uint64_t)req->int_tx_buf + GNI_READ_ALIGN;
}
GNIX_LOG_DUMP_TXD(ct_txd);
COND_ACQUIRE(nic->requires_lock, &nic->lock);
/*
* TODO: need work here too!
*/
if (OFI_UNLIKELY(inject_err)) {
_gnix_nic_txd_err_inject(nic, bte_txd);
status = GNI_RC_SUCCESS;
} else {
status = GNI_PostRdma(req->vc->gni_ep,
&bte_txd->gni_desc);
}
if (status != GNI_RC_SUCCESS) {
COND_RELEASE(nic->requires_lock, &nic->lock);
_gnix_nic_tx_free(nic, ct_txd);
_gnix_nic_tx_free(nic, bte_txd);
GNIX_INFO(FI_LOG_EP_DATA, "GNI_Post*() failed: %s\n",
gni_err_str[status]);
return gnixu_to_fi_errno(status);
}
if (OFI_UNLIKELY(inject_err)) {
_gnix_nic_txd_err_inject(nic, ct_txd);
status = GNI_RC_SUCCESS;
} else if (fma_chain) {
status = GNI_CtPostFma(req->vc->gni_ep,
&ct_txd->gni_desc);
} else {
status = GNI_PostFma(req->vc->gni_ep,
&ct_txd->gni_desc);
}
if (status != GNI_RC_SUCCESS) {
COND_RELEASE(nic->requires_lock, &nic->lock);
_gnix_nic_tx_free(nic, ct_txd);
/* Wait for the first TX to complete, then retransmit the
* entire thing. */
ofi_atomic_set32(&req->rma.outstanding_txds, 1);
req->rma.status = GNI_RC_TRANSACTION_ERROR;
GNIX_INFO(FI_LOG_EP_DATA, "GNI_Post*() failed: %s\n",
gni_err_str[status]);
return FI_SUCCESS;
}
COND_RELEASE(nic->requires_lock, &nic->lock);
/* Wait for both TXs to complete, then process the request. */
ofi_atomic_set32(&req->rma.outstanding_txds, 2);
req->rma.status = 0;
return FI_SUCCESS;
}