Commit 4f44e519 authored by Mustafa Ismail's avatar Mustafa Ismail Committed by Leon Romanovsky

RDMA/irdma: Fix inline for multiple SGE's

Currently, inline send and inline write assume a single
SGE and only copy data from the first one. Add support
for multiple SGE's.

Fixes: b48c24c2 ("RDMA/irdma: Implement device supported verb APIs")
Signed-off-by: default avatarMustafa Ismail <mustafa.ismail@intel.com>
Signed-off-by: default avatarShiraz Saleem <shiraz.saleem@intel.com>
Link: https://lore.kernel.org/r/20221115011701.1379-2-shiraz.saleem@intel.comSigned-off-by: default avatarLeon Romanovsky <leon@kernel.org>
parent 60da2d11
...@@ -566,21 +566,37 @@ static void irdma_set_mw_bind_wqe_gen_1(__le64 *wqe, ...@@ -566,21 +566,37 @@ static void irdma_set_mw_bind_wqe_gen_1(__le64 *wqe,
/** /**
* irdma_copy_inline_data_gen_1 - Copy inline data to wqe * irdma_copy_inline_data_gen_1 - Copy inline data to wqe
* @dest: pointer to wqe * @wqe: pointer to wqe
* @src: pointer to inline data * @sge_list: table of pointers to inline data
* @len: length of inline data to copy * @num_sges: Total inline data length
* @polarity: compatibility parameter * @polarity: compatibility parameter
*/ */
static void irdma_copy_inline_data_gen_1(u8 *dest, u8 *src, u32 len, static void irdma_copy_inline_data_gen_1(u8 *wqe, struct ib_sge *sge_list,
u8 polarity) u32 num_sges, u8 polarity)
{ {
if (len <= 16) { u32 quanta_bytes_remaining = 16;
memcpy(dest, src, len); int i;
} else {
memcpy(dest, src, 16); for (i = 0; i < num_sges; i++) {
src += 16; u8 *cur_sge = (u8 *)(uintptr_t)sge_list[i].addr;
dest = dest + 32; u32 sge_len = sge_list[i].length;
memcpy(dest, src, len - 16);
while (sge_len) {
u32 bytes_copied;
bytes_copied = min(sge_len, quanta_bytes_remaining);
memcpy(wqe, cur_sge, bytes_copied);
wqe += bytes_copied;
cur_sge += bytes_copied;
quanta_bytes_remaining -= bytes_copied;
sge_len -= bytes_copied;
if (!quanta_bytes_remaining) {
/* Remaining inline bytes reside after hdr */
wqe += 16;
quanta_bytes_remaining = 32;
}
}
} }
} }
...@@ -612,35 +628,51 @@ static void irdma_set_mw_bind_wqe(__le64 *wqe, ...@@ -612,35 +628,51 @@ static void irdma_set_mw_bind_wqe(__le64 *wqe,
/** /**
* irdma_copy_inline_data - Copy inline data to wqe * irdma_copy_inline_data - Copy inline data to wqe
* @dest: pointer to wqe * @wqe: pointer to wqe
* @src: pointer to inline data * @sge_list: table of pointers to inline data
* @len: length of inline data to copy * @num_sges: number of SGE's
* @polarity: polarity of wqe valid bit * @polarity: polarity of wqe valid bit
*/ */
static void irdma_copy_inline_data(u8 *dest, u8 *src, u32 len, u8 polarity) static void irdma_copy_inline_data(u8 *wqe, struct ib_sge *sge_list,
u32 num_sges, u8 polarity)
{ {
u8 inline_valid = polarity << IRDMA_INLINE_VALID_S; u8 inline_valid = polarity << IRDMA_INLINE_VALID_S;
u32 copy_size; u32 quanta_bytes_remaining = 8;
bool first_quanta = true;
dest += 8; int i;
if (len <= 8) {
memcpy(dest, src, len); wqe += 8;
return;
} for (i = 0; i < num_sges; i++) {
u8 *cur_sge = (u8 *)(uintptr_t)sge_list[i].addr;
*((u64 *)dest) = *((u64 *)src); u32 sge_len = sge_list[i].length;
len -= 8;
src += 8; while (sge_len) {
dest += 24; /* point to additional 32 byte quanta */ u32 bytes_copied;
while (len) { bytes_copied = min(sge_len, quanta_bytes_remaining);
copy_size = len < 31 ? len : 31; memcpy(wqe, cur_sge, bytes_copied);
memcpy(dest, src, copy_size); wqe += bytes_copied;
*(dest + 31) = inline_valid; cur_sge += bytes_copied;
len -= copy_size; quanta_bytes_remaining -= bytes_copied;
dest += 32; sge_len -= bytes_copied;
src += copy_size;
if (!quanta_bytes_remaining) {
quanta_bytes_remaining = 31;
/* Remaining inline bytes reside after hdr */
if (first_quanta) {
first_quanta = false;
wqe += 16;
} else {
*wqe = inline_valid;
wqe++;
}
}
}
} }
if (!first_quanta && quanta_bytes_remaining < 31)
*(wqe + quanta_bytes_remaining) = inline_valid;
} }
/** /**
...@@ -679,20 +711,27 @@ int irdma_uk_inline_rdma_write(struct irdma_qp_uk *qp, ...@@ -679,20 +711,27 @@ int irdma_uk_inline_rdma_write(struct irdma_qp_uk *qp,
struct irdma_post_sq_info *info, bool post_sq) struct irdma_post_sq_info *info, bool post_sq)
{ {
__le64 *wqe; __le64 *wqe;
struct irdma_inline_rdma_write *op_info; struct irdma_rdma_write *op_info;
u64 hdr = 0; u64 hdr = 0;
u32 wqe_idx; u32 wqe_idx;
bool read_fence = false; bool read_fence = false;
u32 i, total_size = 0;
u16 quanta; u16 quanta;
info->push_wqe = qp->push_db ? true : false; info->push_wqe = qp->push_db ? true : false;
op_info = &info->op.inline_rdma_write; op_info = &info->op.rdma_write;
if (unlikely(qp->max_sq_frag_cnt < op_info->num_lo_sges))
return -EINVAL;
if (op_info->len > qp->max_inline_data) for (i = 0; i < op_info->num_lo_sges; i++)
total_size += op_info->lo_sg_list[i].length;
if (unlikely(total_size > qp->max_inline_data))
return -EINVAL; return -EINVAL;
quanta = qp->wqe_ops.iw_inline_data_size_to_quanta(op_info->len); quanta = qp->wqe_ops.iw_inline_data_size_to_quanta(total_size);
wqe = irdma_qp_get_next_send_wqe(qp, &wqe_idx, quanta, op_info->len, wqe = irdma_qp_get_next_send_wqe(qp, &wqe_idx, quanta, total_size,
info); info);
if (!wqe) if (!wqe)
return -ENOMEM; return -ENOMEM;
...@@ -705,7 +744,7 @@ int irdma_uk_inline_rdma_write(struct irdma_qp_uk *qp, ...@@ -705,7 +744,7 @@ int irdma_uk_inline_rdma_write(struct irdma_qp_uk *qp,
hdr = FIELD_PREP(IRDMAQPSQ_REMSTAG, op_info->rem_addr.lkey) | hdr = FIELD_PREP(IRDMAQPSQ_REMSTAG, op_info->rem_addr.lkey) |
FIELD_PREP(IRDMAQPSQ_OPCODE, info->op_type) | FIELD_PREP(IRDMAQPSQ_OPCODE, info->op_type) |
FIELD_PREP(IRDMAQPSQ_INLINEDATALEN, op_info->len) | FIELD_PREP(IRDMAQPSQ_INLINEDATALEN, total_size) |
FIELD_PREP(IRDMAQPSQ_REPORTRTT, info->report_rtt ? 1 : 0) | FIELD_PREP(IRDMAQPSQ_REPORTRTT, info->report_rtt ? 1 : 0) |
FIELD_PREP(IRDMAQPSQ_INLINEDATAFLAG, 1) | FIELD_PREP(IRDMAQPSQ_INLINEDATAFLAG, 1) |
FIELD_PREP(IRDMAQPSQ_IMMDATAFLAG, info->imm_data_valid ? 1 : 0) | FIELD_PREP(IRDMAQPSQ_IMMDATAFLAG, info->imm_data_valid ? 1 : 0) |
...@@ -719,7 +758,8 @@ int irdma_uk_inline_rdma_write(struct irdma_qp_uk *qp, ...@@ -719,7 +758,8 @@ int irdma_uk_inline_rdma_write(struct irdma_qp_uk *qp,
set_64bit_val(wqe, 0, set_64bit_val(wqe, 0,
FIELD_PREP(IRDMAQPSQ_IMMDATA, info->imm_data)); FIELD_PREP(IRDMAQPSQ_IMMDATA, info->imm_data));
qp->wqe_ops.iw_copy_inline_data((u8 *)wqe, op_info->data, op_info->len, qp->wqe_ops.iw_copy_inline_data((u8 *)wqe, op_info->lo_sg_list,
op_info->num_lo_sges,
qp->swqe_polarity); qp->swqe_polarity);
dma_wmb(); /* make sure WQE is populated before valid bit is set */ dma_wmb(); /* make sure WQE is populated before valid bit is set */
...@@ -745,20 +785,27 @@ int irdma_uk_inline_send(struct irdma_qp_uk *qp, ...@@ -745,20 +785,27 @@ int irdma_uk_inline_send(struct irdma_qp_uk *qp,
struct irdma_post_sq_info *info, bool post_sq) struct irdma_post_sq_info *info, bool post_sq)
{ {
__le64 *wqe; __le64 *wqe;
struct irdma_post_inline_send *op_info; struct irdma_post_send *op_info;
u64 hdr; u64 hdr;
u32 wqe_idx; u32 wqe_idx;
bool read_fence = false; bool read_fence = false;
u32 i, total_size = 0;
u16 quanta; u16 quanta;
info->push_wqe = qp->push_db ? true : false; info->push_wqe = qp->push_db ? true : false;
op_info = &info->op.inline_send; op_info = &info->op.send;
if (op_info->len > qp->max_inline_data) if (unlikely(qp->max_sq_frag_cnt < op_info->num_sges))
return -EINVAL; return -EINVAL;
quanta = qp->wqe_ops.iw_inline_data_size_to_quanta(op_info->len); for (i = 0; i < op_info->num_sges; i++)
wqe = irdma_qp_get_next_send_wqe(qp, &wqe_idx, quanta, op_info->len, total_size += op_info->sg_list[i].length;
if (unlikely(total_size > qp->max_inline_data))
return -EINVAL;
quanta = qp->wqe_ops.iw_inline_data_size_to_quanta(total_size);
wqe = irdma_qp_get_next_send_wqe(qp, &wqe_idx, quanta, total_size,
info); info);
if (!wqe) if (!wqe)
return -ENOMEM; return -ENOMEM;
...@@ -773,7 +820,7 @@ int irdma_uk_inline_send(struct irdma_qp_uk *qp, ...@@ -773,7 +820,7 @@ int irdma_uk_inline_send(struct irdma_qp_uk *qp,
hdr = FIELD_PREP(IRDMAQPSQ_REMSTAG, info->stag_to_inv) | hdr = FIELD_PREP(IRDMAQPSQ_REMSTAG, info->stag_to_inv) |
FIELD_PREP(IRDMAQPSQ_AHID, op_info->ah_id) | FIELD_PREP(IRDMAQPSQ_AHID, op_info->ah_id) |
FIELD_PREP(IRDMAQPSQ_OPCODE, info->op_type) | FIELD_PREP(IRDMAQPSQ_OPCODE, info->op_type) |
FIELD_PREP(IRDMAQPSQ_INLINEDATALEN, op_info->len) | FIELD_PREP(IRDMAQPSQ_INLINEDATALEN, total_size) |
FIELD_PREP(IRDMAQPSQ_IMMDATAFLAG, FIELD_PREP(IRDMAQPSQ_IMMDATAFLAG,
(info->imm_data_valid ? 1 : 0)) | (info->imm_data_valid ? 1 : 0)) |
FIELD_PREP(IRDMAQPSQ_REPORTRTT, (info->report_rtt ? 1 : 0)) | FIELD_PREP(IRDMAQPSQ_REPORTRTT, (info->report_rtt ? 1 : 0)) |
...@@ -789,8 +836,8 @@ int irdma_uk_inline_send(struct irdma_qp_uk *qp, ...@@ -789,8 +836,8 @@ int irdma_uk_inline_send(struct irdma_qp_uk *qp,
if (info->imm_data_valid) if (info->imm_data_valid)
set_64bit_val(wqe, 0, set_64bit_val(wqe, 0,
FIELD_PREP(IRDMAQPSQ_IMMDATA, info->imm_data)); FIELD_PREP(IRDMAQPSQ_IMMDATA, info->imm_data));
qp->wqe_ops.iw_copy_inline_data((u8 *)wqe, op_info->data, op_info->len, qp->wqe_ops.iw_copy_inline_data((u8 *)wqe, op_info->sg_list,
qp->swqe_polarity); op_info->num_sges, qp->swqe_polarity);
dma_wmb(); /* make sure WQE is populated before valid bit is set */ dma_wmb(); /* make sure WQE is populated before valid bit is set */
......
...@@ -173,14 +173,6 @@ struct irdma_post_send { ...@@ -173,14 +173,6 @@ struct irdma_post_send {
u32 ah_id; u32 ah_id;
}; };
struct irdma_post_inline_send {
void *data;
u32 len;
u32 qkey;
u32 dest_qp;
u32 ah_id;
};
struct irdma_post_rq_info { struct irdma_post_rq_info {
u64 wr_id; u64 wr_id;
struct ib_sge *sg_list; struct ib_sge *sg_list;
...@@ -193,12 +185,6 @@ struct irdma_rdma_write { ...@@ -193,12 +185,6 @@ struct irdma_rdma_write {
struct ib_sge rem_addr; struct ib_sge rem_addr;
}; };
struct irdma_inline_rdma_write {
void *data;
u32 len;
struct ib_sge rem_addr;
};
struct irdma_rdma_read { struct irdma_rdma_read {
struct ib_sge *lo_sg_list; struct ib_sge *lo_sg_list;
u32 num_lo_sges; u32 num_lo_sges;
...@@ -241,8 +227,6 @@ struct irdma_post_sq_info { ...@@ -241,8 +227,6 @@ struct irdma_post_sq_info {
struct irdma_rdma_read rdma_read; struct irdma_rdma_read rdma_read;
struct irdma_bind_window bind_window; struct irdma_bind_window bind_window;
struct irdma_inv_local_stag inv_local_stag; struct irdma_inv_local_stag inv_local_stag;
struct irdma_inline_rdma_write inline_rdma_write;
struct irdma_post_inline_send inline_send;
} op; } op;
}; };
...@@ -291,7 +275,8 @@ int irdma_uk_stag_local_invalidate(struct irdma_qp_uk *qp, ...@@ -291,7 +275,8 @@ int irdma_uk_stag_local_invalidate(struct irdma_qp_uk *qp,
bool post_sq); bool post_sq);
struct irdma_wqe_uk_ops { struct irdma_wqe_uk_ops {
void (*iw_copy_inline_data)(u8 *dest, u8 *src, u32 len, u8 polarity); void (*iw_copy_inline_data)(u8 *dest, struct ib_sge *sge_list,
u32 num_sges, u8 polarity);
u16 (*iw_inline_data_size_to_quanta)(u32 data_size); u16 (*iw_inline_data_size_to_quanta)(u32 data_size);
void (*iw_set_fragment)(__le64 *wqe, u32 offset, struct ib_sge *sge, void (*iw_set_fragment)(__le64 *wqe, u32 offset, struct ib_sge *sge,
u8 valid); u8 valid);
......
...@@ -3136,30 +3136,20 @@ static int irdma_post_send(struct ib_qp *ibqp, ...@@ -3136,30 +3136,20 @@ static int irdma_post_send(struct ib_qp *ibqp,
info.stag_to_inv = ib_wr->ex.invalidate_rkey; info.stag_to_inv = ib_wr->ex.invalidate_rkey;
} }
if (ib_wr->send_flags & IB_SEND_INLINE) { info.op.send.num_sges = ib_wr->num_sge;
info.op.inline_send.data = (void *)(unsigned long) info.op.send.sg_list = ib_wr->sg_list;
ib_wr->sg_list[0].addr; if (iwqp->ibqp.qp_type == IB_QPT_UD ||
info.op.inline_send.len = ib_wr->sg_list[0].length; iwqp->ibqp.qp_type == IB_QPT_GSI) {
if (iwqp->ibqp.qp_type == IB_QPT_UD || ah = to_iwah(ud_wr(ib_wr)->ah);
iwqp->ibqp.qp_type == IB_QPT_GSI) { info.op.send.ah_id = ah->sc_ah.ah_info.ah_idx;
ah = to_iwah(ud_wr(ib_wr)->ah); info.op.send.qkey = ud_wr(ib_wr)->remote_qkey;
info.op.inline_send.ah_id = ah->sc_ah.ah_info.ah_idx; info.op.send.dest_qp = ud_wr(ib_wr)->remote_qpn;
info.op.inline_send.qkey = ud_wr(ib_wr)->remote_qkey; }
info.op.inline_send.dest_qp = ud_wr(ib_wr)->remote_qpn;
} if (ib_wr->send_flags & IB_SEND_INLINE)
err = irdma_uk_inline_send(ukqp, &info, false); err = irdma_uk_inline_send(ukqp, &info, false);
} else { else
info.op.send.num_sges = ib_wr->num_sge;
info.op.send.sg_list = ib_wr->sg_list;
if (iwqp->ibqp.qp_type == IB_QPT_UD ||
iwqp->ibqp.qp_type == IB_QPT_GSI) {
ah = to_iwah(ud_wr(ib_wr)->ah);
info.op.send.ah_id = ah->sc_ah.ah_info.ah_idx;
info.op.send.qkey = ud_wr(ib_wr)->remote_qkey;
info.op.send.dest_qp = ud_wr(ib_wr)->remote_qpn;
}
err = irdma_uk_send(ukqp, &info, false); err = irdma_uk_send(ukqp, &info, false);
}
break; break;
case IB_WR_RDMA_WRITE_WITH_IMM: case IB_WR_RDMA_WRITE_WITH_IMM:
if (ukqp->qp_caps & IRDMA_WRITE_WITH_IMM) { if (ukqp->qp_caps & IRDMA_WRITE_WITH_IMM) {
...@@ -3176,22 +3166,15 @@ static int irdma_post_send(struct ib_qp *ibqp, ...@@ -3176,22 +3166,15 @@ static int irdma_post_send(struct ib_qp *ibqp,
else else
info.op_type = IRDMA_OP_TYPE_RDMA_WRITE; info.op_type = IRDMA_OP_TYPE_RDMA_WRITE;
if (ib_wr->send_flags & IB_SEND_INLINE) { info.op.rdma_write.num_lo_sges = ib_wr->num_sge;
info.op.inline_rdma_write.data = (void *)(uintptr_t)ib_wr->sg_list[0].addr; info.op.rdma_write.lo_sg_list = ib_wr->sg_list;
info.op.inline_rdma_write.len = info.op.rdma_write.rem_addr.addr =
ib_wr->sg_list[0].length; rdma_wr(ib_wr)->remote_addr;
info.op.inline_rdma_write.rem_addr.addr = info.op.rdma_write.rem_addr.lkey = rdma_wr(ib_wr)->rkey;
rdma_wr(ib_wr)->remote_addr; if (ib_wr->send_flags & IB_SEND_INLINE)
info.op.inline_rdma_write.rem_addr.lkey =
rdma_wr(ib_wr)->rkey;
err = irdma_uk_inline_rdma_write(ukqp, &info, false); err = irdma_uk_inline_rdma_write(ukqp, &info, false);
} else { else
info.op.rdma_write.lo_sg_list = (void *)ib_wr->sg_list;
info.op.rdma_write.num_lo_sges = ib_wr->num_sge;
info.op.rdma_write.rem_addr.addr = rdma_wr(ib_wr)->remote_addr;
info.op.rdma_write.rem_addr.lkey = rdma_wr(ib_wr)->rkey;
err = irdma_uk_rdma_write(ukqp, &info, false); err = irdma_uk_rdma_write(ukqp, &info, false);
}
break; break;
case IB_WR_RDMA_READ_WITH_INV: case IB_WR_RDMA_READ_WITH_INV:
inv_stag = true; inv_stag = true;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment