#include "config.h"
#include "fi_verbs.h"
static ssize_t
fi_ibv_msg_ep_recvmsg(struct fid_ep *ep, const struct fi_msg *msg, uint64_t flags)
{
struct fi_ibv_msg_ep *_ep;
struct ibv_recv_wr wr, *bad;
struct ibv_sge *sge = NULL;
ssize_t ret;
size_t i;
_ep = container_of(ep, struct fi_ibv_msg_ep, ep_fid);
assert(_ep->rcq);
wr.wr_id = (uintptr_t) msg->context;
wr.next = NULL;
if (msg->iov_count) {
sge = alloca(sizeof(*sge) * msg->iov_count);
for (i = 0; i < msg->iov_count; i++) {
sge[i].addr = (uintptr_t) msg->msg_iov[i].iov_base;
sge[i].length = (uint32_t) msg->msg_iov[i].iov_len;
sge[i].lkey = (uint32_t) (uintptr_t) (msg->desc[i]);
}
}
wr.sg_list = sge;
wr.num_sge = msg->iov_count;
ret = ibv_post_recv(_ep->id->qp, &wr, &bad);
switch (ret) {
case ENOMEM:
return -FI_EAGAIN;
case -1:
return (errno == ENOMEM) ? -FI_EAGAIN : -errno;
default:
return -ret;
}
}
static ssize_t
fi_ibv_msg_ep_recv(struct fid_ep *ep, void *buf, size_t len,
void *desc, fi_addr_t src_addr, void *context)
{
struct iovec iov;
struct fi_msg msg;
iov.iov_base = buf;
iov.iov_len = len;
msg.msg_iov = &iov;
msg.desc = &desc;
msg.iov_count = 1;
msg.addr = src_addr;
msg.context = context;
return fi_ibv_msg_ep_recvmsg(ep, &msg, 0);
}
static ssize_t
fi_ibv_msg_ep_recvv(struct fid_ep *ep, const struct iovec *iov, void **desc,
size_t count, fi_addr_t src_addr, void *context)
{
struct fi_msg msg;
msg.msg_iov = iov;
msg.desc = desc;
msg.iov_count = count;
msg.addr = src_addr;
msg.context = context;
return fi_ibv_msg_ep_recvmsg(ep, &msg, 0);
}
static ssize_t
fi_ibv_msg_ep_sendmsg(struct fid_ep *ep_fid, const struct fi_msg *msg, uint64_t flags)
{
struct fi_ibv_msg_ep *ep;
struct ibv_send_wr wr;
memset(&wr, 0, sizeof(wr));
if (flags & FI_REMOTE_CQ_DATA) {
wr.opcode = IBV_WR_SEND_WITH_IMM;
wr.imm_data = htonl((uint32_t)msg->data);
} else {
wr.opcode = IBV_WR_SEND;
}
ep = container_of(ep_fid, struct fi_ibv_msg_ep, ep_fid);
return fi_ibv_send_msg(ep, &wr, msg, flags);
}
static ssize_t
fi_ibv_msg_ep_send(struct fid_ep *ep_fid, const void *buf, size_t len,
void *desc, fi_addr_t dest_addr, void *context)
{
struct fi_ibv_msg_ep *ep;
struct ibv_send_wr wr;
memset(&wr, 0, sizeof(wr));
wr.opcode = IBV_WR_SEND;
ep = container_of(ep_fid, struct fi_ibv_msg_ep, ep_fid);
wr.send_flags = VERBS_INJECT(ep, len) | VERBS_COMP(ep);
return fi_ibv_send_buf(ep, &wr, buf, len, desc, context);
}
static ssize_t
fi_ibv_msg_ep_senddata(struct fid_ep *ep_fid, const void *buf, size_t len,
void *desc, uint64_t data, fi_addr_t dest_addr, void *context)
{
struct fi_ibv_msg_ep *ep;
struct ibv_send_wr wr;
memset(&wr, 0, sizeof(wr));
wr.opcode = IBV_WR_SEND_WITH_IMM;
wr.imm_data = htonl((uint32_t)data);
ep = container_of(ep_fid, struct fi_ibv_msg_ep, ep_fid);
wr.send_flags = VERBS_INJECT(ep, len) | VERBS_COMP(ep);
return fi_ibv_send_buf(ep, &wr, buf, len, desc, context);
}
static ssize_t
fi_ibv_msg_ep_sendv(struct fid_ep *ep_fid, const struct iovec *iov, void **desc,
size_t count, fi_addr_t dest_addr, void *context)
{
struct fi_ibv_msg_ep *ep;
struct ibv_send_wr wr;
memset(&wr, 0, sizeof(wr));
wr.opcode = IBV_WR_SEND;
ep = container_of(ep_fid, struct fi_ibv_msg_ep, ep_fid);
return fi_ibv_send_iov(ep, &wr, iov, desc, count, context);
}
static ssize_t fi_ibv_msg_ep_inject(struct fid_ep *ep_fid, const void *buf, size_t len,
fi_addr_t dest_addr)
{
struct fi_ibv_msg_ep *ep;
struct ibv_send_wr wr;
memset(&wr, 0, sizeof(wr));
wr.opcode = IBV_WR_SEND;
wr.send_flags = IBV_SEND_INLINE;
ep = container_of(ep_fid, struct fi_ibv_msg_ep, ep_fid);
return fi_ibv_send_buf_inline(ep, &wr, buf, len);
}
static ssize_t fi_ibv_msg_ep_injectdata(struct fid_ep *ep_fid, const void *buf, size_t len,
uint64_t data, fi_addr_t dest_addr)
{
struct fi_ibv_msg_ep *ep;
struct ibv_send_wr wr;
memset(&wr, 0, sizeof(wr));
wr.opcode = IBV_WR_SEND_WITH_IMM;
wr.imm_data = htonl((uint32_t)data);
wr.send_flags = IBV_SEND_INLINE;
ep = container_of(ep_fid, struct fi_ibv_msg_ep, ep_fid);
return fi_ibv_send_buf_inline(ep, &wr, buf, len);
}
static struct fi_ops_msg fi_ibv_msg_ep_msg_ops = {
.size = sizeof(struct fi_ops_msg),
.recv = fi_ibv_msg_ep_recv,
.recvv = fi_ibv_msg_ep_recvv,
.recvmsg = fi_ibv_msg_ep_recvmsg,
.send = fi_ibv_msg_ep_send,
.sendv = fi_ibv_msg_ep_sendv,
.sendmsg = fi_ibv_msg_ep_sendmsg,
.inject = fi_ibv_msg_ep_inject,
.senddata = fi_ibv_msg_ep_senddata,
.injectdata = fi_ibv_msg_ep_injectdata,
};
struct fi_ops_msg *fi_ibv_msg_ep_ops_msg(struct fi_ibv_msg_ep *ep)
{
return &fi_ibv_msg_ep_msg_ops;
}
static struct fi_ops_msg fi_ibv_msg_srq_ep_msg_ops = {
.size = sizeof(struct fi_ops_msg),
.recv = fi_no_msg_recv,
.recvv = fi_no_msg_recvv,
.recvmsg = fi_no_msg_recvmsg,
.send = fi_ibv_msg_ep_send,
.sendv = fi_ibv_msg_ep_sendv,
.sendmsg = fi_ibv_msg_ep_sendmsg,
.inject = fi_ibv_msg_ep_inject,
.senddata = fi_ibv_msg_ep_senddata,
.injectdata = fi_ibv_msg_ep_injectdata,
};
struct fi_ops_msg *fi_ibv_msg_srq_ep_ops_msg(struct fi_ibv_msg_ep *ep)
{
return &fi_ibv_msg_srq_ep_msg_ops;
}