new feature: - support diamond products - support ibv_wr apis - support extended CQ poll apis bugfix: - imm data endian error Signed-off-by: Xin Tian <tianx@yunsilicon.com> (cherry picked from commit d12a87881cb9254bb46cfdde6131428a139f15bb)
2743 lines
82 KiB
Diff
2743 lines
82 KiB
Diff
From 81a2efc28f60ab26398c45236678cc08518b1e41 Mon Sep 17 00:00:00 2001
|
|
From: Xin Tian <tianx@yunsilicon.com>
|
|
Date: Thu, 8 May 2025 12:10:40 +0800
|
|
Subject: [PATCH] libxscale: update to version 2412GA
|
|
|
|
new feature:
|
|
- support diamond products
|
|
- support ibv_wr apis
|
|
- support extended CQ poll apis
|
|
|
|
bugfix:
|
|
- imm data endian error
|
|
|
|
Signed-off-by: Xin Tian <tianx@yunsilicon.com>
|
|
---
|
|
providers/xscale/cq.c | 1047 ++++++++++--------------------------
|
|
providers/xscale/qp.c | 516 ++++++++++++++----
|
|
providers/xscale/verbs.c | 175 ++++--
|
|
providers/xscale/xsc_api.h | 4 +-
|
|
providers/xscale/xsc_hsi.h | 103 ++--
|
|
providers/xscale/xscale.c | 12 +-
|
|
providers/xscale/xscale.h | 37 +-
|
|
7 files changed, 923 insertions(+), 971 deletions(-)
|
|
|
|
diff --git a/providers/xscale/cq.c b/providers/xscale/cq.c
|
|
index e2619f0..609ce2e 100644
|
|
--- a/providers/xscale/cq.c
|
|
+++ b/providers/xscale/cq.c
|
|
@@ -13,12 +13,12 @@
|
|
#include <unistd.h>
|
|
|
|
#include <util/compiler.h>
|
|
-#include <util/mmio.h>
|
|
#include <infiniband/opcode.h>
|
|
|
|
#include "xscale.h"
|
|
#include "wqe.h"
|
|
#include "xsc_hsi.h"
|
|
+#include "xsc_hw.h"
|
|
|
|
enum {
|
|
CQ_OK = 0,
|
|
@@ -68,6 +68,7 @@ static const uint32_t xsc_cqe_opcode[] = {
|
|
[XSC_OPCODE_RDMA_REQ_WRITE_IMMDT] = IBV_WC_RDMA_WRITE,
|
|
[XSC_OPCODE_RDMA_RSP_WRITE_IMMDT] = IBV_WC_RECV_RDMA_WITH_IMM,
|
|
[XSC_OPCODE_RDMA_REQ_READ] = IBV_WC_RDMA_READ,
|
|
+ [XSC_OPCODE_RDMA_CQE_RAW_SNF] = IBV_WC_RECV,
|
|
};
|
|
|
|
int xsc_stall_num_loop = 60;
|
|
@@ -76,16 +77,64 @@ int xsc_stall_cq_poll_max = 100000;
|
|
int xsc_stall_cq_inc_step = 100;
|
|
int xsc_stall_cq_dec_step = 10;
|
|
|
|
-static inline uint8_t xsc_get_cqe_opcode(struct xsc_cqe *cqe) ALWAYS_INLINE;
|
|
-static inline uint8_t xsc_get_cqe_opcode(struct xsc_cqe *cqe)
|
|
+static void xsc_stall_poll_cq(void)
|
|
+{
|
|
+ int i;
|
|
+
|
|
+ for (i = 0; i < xsc_stall_num_loop; i++)
|
|
+ __asm__ volatile ("nop");
|
|
+}
|
|
+
|
|
+static inline int get_qp_ctx(struct xsc_context *xctx,
|
|
+ struct xsc_resource **cur_rsc,
|
|
+ uint32_t qpn)
|
|
+ ALWAYS_INLINE;
|
|
+static inline int get_qp_ctx(struct xsc_context *xctx,
|
|
+ struct xsc_resource **cur_rsc,
|
|
+ uint32_t qpn)
|
|
+{
|
|
+ if (!*cur_rsc || (qpn != (*cur_rsc)->rsn)) {
|
|
+ /*
|
|
+ * We do not have to take the QP table lock here,
|
|
+ * because CQs will be locked while QPs are removed
|
|
+ * from the table.
|
|
+ */
|
|
+ *cur_rsc = (struct xsc_resource *)xsc_find_qp(xctx, qpn);
|
|
+ if (unlikely(!*cur_rsc))
|
|
+ return CQ_POLL_ERR;
|
|
+ }
|
|
+
|
|
+ return CQ_OK;
|
|
+}
|
|
+
|
|
+static inline uint8_t xsc_get_cqe_opcode(struct xsc_context *ctx,
|
|
+ struct xsc_resource **cur_rsc,
|
|
+ struct xsc_cqe *cqe) ALWAYS_INLINE;
|
|
+static inline uint8_t xsc_get_cqe_opcode(struct xsc_context *ctx,
|
|
+ struct xsc_resource **cur_rsc,
|
|
+ struct xsc_cqe *cqe)
|
|
{
|
|
- if (cqe->is_error)
|
|
+ uint8_t msg_opcode = xsc_hw_get_cqe_msg_opcode(ctx->device_id, cqe);
|
|
+ struct xsc_qp *qp;
|
|
+ int err;
|
|
+
|
|
+ if (xsc_hw_is_err_cqe(ctx->device_id, cqe))
|
|
return cqe->type ? XSC_OPCODE_RDMA_RSP_ERROR : XSC_OPCODE_RDMA_REQ_ERROR;
|
|
- if (cqe->msg_opcode > XSC_MSG_OPCODE_RDMA_READ) {
|
|
+
|
|
+ err = get_qp_ctx(ctx, cur_rsc, RD_LE_16(cqe->qp_id));
|
|
+ if (unlikely(err))
|
|
+ goto msg_opcode_err_check;
|
|
+ qp = rsc_to_xqp(*cur_rsc);
|
|
+ if (qp->flags & XSC_QP_FLAG_RAWPACKET_SNIFFER)
|
|
+ return XSC_OPCODE_RDMA_CQE_RAW_SNF;
|
|
+
|
|
+msg_opcode_err_check:
|
|
+ if (msg_opcode > XSC_MSG_OPCODE_RDMA_READ) {
|
|
printf("rdma cqe msg code should be send/write/read\n");
|
|
return XSC_OPCODE_RDMA_CQE_ERROR;
|
|
}
|
|
- return xsc_msg_opcode[cqe->msg_opcode][cqe->type][cqe->with_immdt];
|
|
+
|
|
+ return xsc_msg_opcode[msg_opcode][cqe->type][cqe->with_immdt];
|
|
}
|
|
|
|
static inline uint8_t get_cqe_l3_hdr_type(struct xsc_cqe64 *cqe)
|
|
@@ -108,18 +157,11 @@ static void *get_sw_cqe(struct xsc_cq *cq, int n)
|
|
return NULL;
|
|
}
|
|
|
|
-static void *next_cqe_sw(struct xsc_cq *cq)
|
|
-{
|
|
- return get_sw_cqe(cq, cq->cons_index);
|
|
-}
|
|
-
|
|
static void update_cons_index(struct xsc_cq *cq)
|
|
{
|
|
- union xsc_db_data db;
|
|
+ struct xsc_context *ctx = to_xctx(ibv_cq_ex_to_cq(&cq->verbs_cq.cq_ex)->context);
|
|
|
|
- db.raw_data = cq->cons_index;
|
|
- db.cqn = cq->cqn;
|
|
- WR_REG(cq->db, db.raw_data);
|
|
+ xsc_hw_set_cq_ci(ctx->device_id, cq->db, cq->cqn, cq->cons_index);
|
|
}
|
|
|
|
static inline void handle_good_req(
|
|
@@ -140,6 +182,7 @@ static inline void handle_good_req(
|
|
wc->byte_len = ctrl->msg_len;
|
|
}
|
|
wq->flush_wqe_cnt--;
|
|
+ wq->need_flush[idx] = 0;
|
|
|
|
xsc_dbg(to_xctx(qp->ibv_qp->context)->dbg_fp, XSC_DBG_CQ_CQE,
|
|
"wqeid:%u, wq tail:%u\n", idx, wq->tail);
|
|
@@ -182,40 +225,6 @@ static void dump_cqe(void *buf)
|
|
printf("0x%08x 0x%08x 0x%08x 0x%08x\n", p[i], p[i+1], p[i+2], p[i+3]);
|
|
}
|
|
|
|
-static enum ibv_wc_status xsc_cqe_error_code(struct xsc_cqe *cqe)
|
|
-{
|
|
- switch (cqe->error_code) {
|
|
- case XSC_ERR_CODE_NAK_RETRY:
|
|
- return IBV_WC_RETRY_EXC_ERR;
|
|
- case XSC_ERR_CODE_NAK_OPCODE:
|
|
- return IBV_WC_BAD_RESP_ERR;
|
|
- case XSC_ERR_CODE_NAK_MR:
|
|
- return IBV_WC_REM_ACCESS_ERR;
|
|
- case XSC_ERR_CODE_NAK_OPERATION:
|
|
- return IBV_WC_REM_OP_ERR;
|
|
- case XSC_ERR_CODE_NAK_RNR:
|
|
- return IBV_WC_RNR_RETRY_EXC_ERR;
|
|
- case XSC_ERR_CODE_LOCAL_MR:
|
|
- return IBV_WC_LOC_PROT_ERR;
|
|
- case XSC_ERR_CODE_LOCAL_LEN:
|
|
- return IBV_WC_LOC_LEN_ERR;
|
|
- case XSC_ERR_CODE_LEN_GEN_CQE:
|
|
- return IBV_WC_LOC_LEN_ERR;
|
|
- case XSC_ERR_CODE_OPERATION:
|
|
- return IBV_WC_LOC_ACCESS_ERR;
|
|
- case XSC_ERR_CODE_FLUSH:
|
|
- return IBV_WC_WR_FLUSH_ERR;
|
|
- case XSC_ERR_CODE_MALF_WQE_HOST:
|
|
- case XSC_ERR_CODE_STRG_ACC_GEN_CQE:
|
|
- return IBV_WC_FATAL_ERR;
|
|
- case XSC_ERR_CODE_OPCODE_GEN_CQE:
|
|
- case XSC_ERR_CODE_LOCAL_OPCODE:
|
|
- default:
|
|
- return IBV_WC_GENERAL_ERR;
|
|
- }
|
|
-}
|
|
-
|
|
-
|
|
static inline bool xsc_qp_need_cqe(struct xsc_qp *qp, int *type, int *wqe_id)
|
|
{
|
|
struct xsc_wq *wq;
|
|
@@ -248,128 +257,49 @@ static inline void handle_bad_req(
|
|
struct ibv_wc *wc, struct xsc_cqe *cqe, struct xsc_qp *qp, struct xsc_wq *wq)
|
|
{
|
|
int idx;
|
|
- wc->status = xsc_cqe_error_code(cqe);
|
|
- wc->vendor_err = cqe->error_code;
|
|
+
|
|
+ wc->status = xsc_hw_cqe_err_status(xctx->device_id, cqe);
|
|
+ wc->vendor_err = xsc_hw_get_cqe_err_code(xctx->device_id, cqe);
|
|
idx = RD_LE_16(cqe->wqe_id);
|
|
idx >>= (qp->sq.wqe_shift - XSC_BASE_WQE_SHIFT);
|
|
idx &= (wq->wqe_cnt -1);
|
|
wq->tail = wq->wqe_head[idx] + 1;
|
|
wc->wr_id = wq->wrid[idx];
|
|
- wq->flush_wqe_cnt--;
|
|
-
|
|
- if (cqe->error_code != XSC_ERR_CODE_FLUSH) {
|
|
+ if (wq->need_flush[idx])
|
|
+ wq->flush_wqe_cnt--;
|
|
+ wq->need_flush[idx] = 0;
|
|
+ if (wc->status != IBV_WC_WR_FLUSH_ERR) {
|
|
printf("%s: got completion with error:\n", xctx->hostname);
|
|
dump_cqe(cqe);
|
|
}
|
|
+ qp->err_occurred = 1;
|
|
}
|
|
|
|
static inline void handle_bad_responder(
|
|
struct xsc_context *xctx,
|
|
- struct ibv_wc *wc, struct xsc_cqe *cqe, struct xsc_wq *wq)
|
|
+ struct ibv_wc *wc, struct xsc_cqe *cqe, struct xsc_qp *qp, struct xsc_wq *wq)
|
|
{
|
|
- wc->status = xsc_cqe_error_code(cqe);
|
|
- wc->vendor_err = cqe->error_code;
|
|
+ wc->status = xsc_hw_cqe_err_status(xctx->device_id, cqe);
|
|
+ wc->vendor_err = xsc_hw_get_cqe_err_code(xctx->device_id, cqe);
|
|
|
|
++wq->tail;
|
|
wq->flush_wqe_cnt--;
|
|
-
|
|
- if (cqe->error_code != XSC_ERR_CODE_FLUSH) {
|
|
+ if (wc->status != IBV_WC_WR_FLUSH_ERR) {
|
|
printf("%s: got completion with error:\n", xctx->hostname);
|
|
dump_cqe(cqe);
|
|
}
|
|
-}
|
|
-
|
|
-#if defined(__x86_64__) || defined (__i386__)
|
|
-static inline unsigned long get_cycles(void)
|
|
-{
|
|
- uint32_t low, high;
|
|
- uint64_t val;
|
|
- asm volatile ("rdtsc" : "=a" (low), "=d" (high));
|
|
- val = high;
|
|
- val = (val << 32) | low;
|
|
- return val;
|
|
-}
|
|
-
|
|
-static void xsc_stall_poll_cq(void)
|
|
-{
|
|
- int i;
|
|
-
|
|
- for (i = 0; i < xsc_stall_num_loop; i++)
|
|
- (void)get_cycles();
|
|
-}
|
|
-static void xsc_stall_cycles_poll_cq(uint64_t cycles)
|
|
-{
|
|
- while (get_cycles() < cycles)
|
|
- ; /* Nothing */
|
|
-}
|
|
-static void xsc_get_cycles(uint64_t *cycles)
|
|
-{
|
|
- *cycles = get_cycles();
|
|
-}
|
|
-#else
|
|
-static void xsc_stall_poll_cq(void)
|
|
-{
|
|
-}
|
|
-static void xsc_stall_cycles_poll_cq(uint64_t cycles)
|
|
-{
|
|
-}
|
|
-static void xsc_get_cycles(uint64_t *cycles)
|
|
-{
|
|
-}
|
|
-#endif
|
|
-
|
|
-static inline int get_qp_ctx(struct xsc_context *xctx,
|
|
- struct xsc_resource **cur_rsc,
|
|
- uint32_t qpn)
|
|
- ALWAYS_INLINE;
|
|
-static inline int get_qp_ctx(struct xsc_context *xctx,
|
|
- struct xsc_resource **cur_rsc,
|
|
- uint32_t qpn)
|
|
-{
|
|
- if (!*cur_rsc || (qpn != (*cur_rsc)->rsn)) {
|
|
- /*
|
|
- * We do not have to take the QP table lock here,
|
|
- * because CQs will be locked while QPs are removed
|
|
- * from the table.
|
|
- */
|
|
- *cur_rsc = (struct xsc_resource *)xsc_find_qp(xctx, qpn);
|
|
- if (unlikely(!*cur_rsc))
|
|
- return CQ_POLL_ERR;
|
|
- }
|
|
-
|
|
- return CQ_OK;
|
|
-}
|
|
-
|
|
-static inline int xsc_get_next_cqe(struct xsc_cq *cq,
|
|
- struct xsc_cqe64 **pcqe64,
|
|
- void **pcqe)
|
|
- ALWAYS_INLINE;
|
|
-static inline int xsc_get_next_cqe(struct xsc_cq *cq,
|
|
- struct xsc_cqe64 **pcqe64,
|
|
- void **pcqe)
|
|
-{
|
|
- void *cqe = next_cqe_sw(cq);
|
|
- if (!cqe)
|
|
- return CQ_EMPTY;
|
|
-
|
|
- ++cq->cons_index;
|
|
-
|
|
- /*
|
|
- * Make sure we read CQ entry contents after we've checked the
|
|
- * ownership bit.
|
|
- */
|
|
- udma_from_device_barrier();
|
|
-
|
|
- *pcqe = cqe;
|
|
-
|
|
- return CQ_OK;
|
|
+ qp->err_occurred = 1;
|
|
}
|
|
|
|
static inline int xsc_parse_cqe(struct xsc_cq *cq,
|
|
- struct xsc_cqe *cqe,
|
|
- struct xsc_resource **cur_rsc,
|
|
- struct ibv_wc *wc,
|
|
- int lazy)
|
|
+ struct xsc_cqe *cqe,
|
|
+ struct xsc_resource **cur_rsc,
|
|
+ struct ibv_wc *wc)
|
|
+ ALWAYS_INLINE;
|
|
+static inline int xsc_parse_cqe(struct xsc_cq *cq,
|
|
+ struct xsc_cqe *cqe,
|
|
+ struct xsc_resource **cur_rsc,
|
|
+ struct ibv_wc *wc)
|
|
{
|
|
struct xsc_wq *wq;
|
|
uint32_t qp_id;
|
|
@@ -378,12 +308,14 @@ static inline int xsc_parse_cqe(struct xsc_cq *cq,
|
|
struct xsc_qp *xqp = NULL;
|
|
struct xsc_context *xctx;
|
|
|
|
+ memset(wc, 0, sizeof(*wc));
|
|
+ wc->wc_flags = 0;
|
|
+
|
|
xctx = to_xctx(ibv_cq_ex_to_cq(&cq->verbs_cq.cq_ex)->context);
|
|
qp_id = cqe->qp_id;
|
|
qp_id = RD_LE_16(qp_id);
|
|
- wc->wc_flags = 0;
|
|
wc->qp_num = qp_id;
|
|
- opcode = xsc_get_cqe_opcode(cqe);
|
|
+ opcode = xsc_get_cqe_opcode(xctx, cur_rsc, cqe);
|
|
|
|
xsc_dbg(xctx->dbg_fp, XSC_DBG_CQ_CQE, "opcode:0x%x qp_num:%u\n", opcode, qp_id);
|
|
switch (opcode) {
|
|
@@ -404,8 +336,9 @@ static inline int xsc_parse_cqe(struct xsc_cq *cq,
|
|
case XSC_OPCODE_RDMA_RSP_RECV_IMMDT:
|
|
case XSC_OPCODE_RDMA_RSP_WRITE_IMMDT:
|
|
wc->wc_flags |= IBV_WC_WITH_IMM;
|
|
- wc->imm_data = cqe->imm_data;
|
|
+ WR_BE_32(wc->imm_data, RD_LE_32(cqe->imm_data));
|
|
SWITCH_FALLTHROUGH;
|
|
+ case XSC_OPCODE_RDMA_CQE_RAW_SNF:
|
|
case XSC_OPCODE_RDMA_RSP_RECV:
|
|
err = get_qp_ctx(xctx, cur_rsc, qp_id);
|
|
if (unlikely(err))
|
|
@@ -428,7 +361,7 @@ static inline int xsc_parse_cqe(struct xsc_cq *cq,
|
|
return CQ_POLL_ERR;
|
|
xqp = rsc_to_xqp(*cur_rsc);
|
|
wq = &xqp->rq;
|
|
- handle_bad_responder(xctx, wc, cqe, wq);
|
|
+ handle_bad_responder(xctx, wc, cqe, xqp, wq);
|
|
break;
|
|
case XSC_OPCODE_RDMA_CQE_ERROR:
|
|
printf("%s: got completion with cqe format error:\n", xctx->hostname);
|
|
@@ -440,30 +373,121 @@ static inline int xsc_parse_cqe(struct xsc_cq *cq,
|
|
return CQ_OK;
|
|
}
|
|
|
|
-static inline int xsc_parse_lazy_cqe(struct xsc_cq *cq,
|
|
- struct xsc_cqe64 *cqe64,
|
|
- void *cqe, int cqe_ver)
|
|
- ALWAYS_INLINE;
|
|
-static inline int xsc_parse_lazy_cqe(struct xsc_cq *cq,
|
|
- struct xsc_cqe64 *cqe64,
|
|
- void *cqe, int cqe_ver)
|
|
+static inline int xsc_parse_cqe_lazy(struct xsc_cq *cq, struct xsc_cqe *cqe) ALWAYS_INLINE;
|
|
+static inline int xsc_parse_cqe_lazy(struct xsc_cq *cq, struct xsc_cqe *cqe)
|
|
{
|
|
- return xsc_parse_cqe(cq, cqe, &cq->cur_rsc, NULL, 1);
|
|
+ struct xsc_resource *cur_rsc = NULL;
|
|
+ struct xsc_qp *xqp = NULL;
|
|
+ struct xsc_context *xctx;
|
|
+ struct xsc_wq *wq;
|
|
+ uint32_t qp_id;
|
|
+ uint8_t opcode;
|
|
+ int err = 0;
|
|
+ int idx;
|
|
+
|
|
+ cq->cqe = cqe;
|
|
+ xctx = to_xctx(ibv_cq_ex_to_cq(&cq->verbs_cq.cq_ex)->context);
|
|
+ qp_id = cqe->qp_id;
|
|
+ qp_id = RD_LE_16(qp_id);
|
|
+ opcode = xsc_get_cqe_opcode(xctx, &cur_rsc, cqe);
|
|
+
|
|
+ xsc_dbg(xctx->dbg_fp, XSC_DBG_CQ_CQE, "opcode:0x%x qp_num:%u\n", opcode, qp_id);
|
|
+ switch (opcode) {
|
|
+ case XSC_OPCODE_RDMA_REQ_SEND_IMMDT:
|
|
+ case XSC_OPCODE_RDMA_REQ_WRITE_IMMDT:
|
|
+ case XSC_OPCODE_RDMA_REQ_SEND:
|
|
+ case XSC_OPCODE_RDMA_REQ_WRITE:
|
|
+ case XSC_OPCODE_RDMA_REQ_READ:
|
|
+ cq->verbs_cq.cq_ex.status = IBV_WC_SUCCESS;
|
|
+ err = get_qp_ctx(xctx, &cur_rsc, qp_id);
|
|
+ if (unlikely(err))
|
|
+ return CQ_EMPTY;
|
|
+ xqp = rsc_to_xqp(cur_rsc);
|
|
+ wq = &xqp->sq;
|
|
+ idx = RD_LE_16(cqe->wqe_id);
|
|
+ idx >>= (wq->wqe_shift - XSC_BASE_WQE_SHIFT);
|
|
+ idx &= (wq->wqe_cnt - 1);
|
|
+ cq->verbs_cq.cq_ex.wr_id = wq->wrid[idx];
|
|
+ wq->tail = wq->wqe_head[idx] + 1;
|
|
+ wq->flush_wqe_cnt--;
|
|
+ wq->need_flush[idx] = 0;
|
|
+ break;
|
|
+ case XSC_OPCODE_RDMA_RSP_RECV_IMMDT:
|
|
+ case XSC_OPCODE_RDMA_RSP_WRITE_IMMDT:
|
|
+ case XSC_OPCODE_RDMA_RSP_RECV:
|
|
+ cq->verbs_cq.cq_ex.status = IBV_WC_SUCCESS;
|
|
+ err = get_qp_ctx(xctx, &cur_rsc, qp_id);
|
|
+ if (unlikely(err))
|
|
+ return CQ_EMPTY;
|
|
+ xqp = rsc_to_xqp(cur_rsc);
|
|
+ wq = &xqp->rq;
|
|
+ idx = wq->tail & (wq->wqe_cnt - 1);
|
|
+ cq->verbs_cq.cq_ex.wr_id = wq->wrid[idx];
|
|
+ ++wq->tail;
|
|
+ wq->flush_wqe_cnt--;
|
|
+ break;
|
|
+ case XSC_OPCODE_RDMA_REQ_ERROR:
|
|
+ cq->verbs_cq.cq_ex.status = xsc_hw_cqe_err_status(xctx->device_id, cqe);
|
|
+ err = get_qp_ctx(xctx, &cur_rsc, qp_id);
|
|
+ if (unlikely(err))
|
|
+ return CQ_POLL_ERR;
|
|
+ xqp = rsc_to_xqp(cur_rsc);
|
|
+ wq = &xqp->sq;
|
|
+ idx = RD_LE_16(cqe->wqe_id);
|
|
+ idx >>= (wq->wqe_shift - XSC_BASE_WQE_SHIFT);
|
|
+ idx &= (wq->wqe_cnt - 1);
|
|
+ wq->tail = wq->wqe_head[idx] + 1;
|
|
+ cq->verbs_cq.cq_ex.wr_id = wq->wrid[idx];
|
|
+ if (wq->need_flush[idx])
|
|
+ wq->flush_wqe_cnt--;
|
|
+ wq->need_flush[idx] = 0;
|
|
+ if (cq->verbs_cq.cq_ex.status != IBV_WC_WR_FLUSH_ERR) {
|
|
+ printf("%s: got completion with error:\n", xctx->hostname);
|
|
+ dump_cqe(cqe);
|
|
+ }
|
|
+ xqp->ibv_qp->state = IBV_QPS_ERR;
|
|
+ break;
|
|
+ case XSC_OPCODE_RDMA_RSP_ERROR:
|
|
+ cq->verbs_cq.cq_ex.status = xsc_hw_cqe_err_status(xctx->device_id, cqe);
|
|
+ err = get_qp_ctx(xctx, &cur_rsc, qp_id);
|
|
+ if (unlikely(err))
|
|
+ return CQ_POLL_ERR;
|
|
+ xqp = rsc_to_xqp(cur_rsc);
|
|
+ wq = &xqp->rq;
|
|
+
|
|
+ ++wq->tail;
|
|
+ wq->flush_wqe_cnt--;
|
|
+ if (cq->verbs_cq.cq_ex.status != IBV_WC_WR_FLUSH_ERR) {
|
|
+ printf("%s: got completion with error:\n", xctx->hostname);
|
|
+ dump_cqe(cqe);
|
|
+ }
|
|
+ xqp->ibv_qp->state = IBV_QPS_ERR;
|
|
+ break;
|
|
+ case XSC_OPCODE_RDMA_CQE_ERROR:
|
|
+ printf("%s: got completion with cqe format error:\n", xctx->hostname);
|
|
+ dump_cqe(cqe);
|
|
+ SWITCH_FALLTHROUGH;
|
|
+ default:
|
|
+ return CQ_POLL_ERR;
|
|
+ }
|
|
+ return CQ_OK;
|
|
}
|
|
|
|
static inline int xsc_poll_one(struct xsc_cq *cq,
|
|
struct xsc_resource **cur_rsc,
|
|
- struct ibv_wc *wc)
|
|
+ struct ibv_wc *wc,
|
|
+ int lazy)
|
|
ALWAYS_INLINE;
|
|
static inline int xsc_poll_one(struct xsc_cq *cq,
|
|
struct xsc_resource **cur_rsc,
|
|
- struct ibv_wc *wc)
|
|
+ struct ibv_wc *wc,
|
|
+ int lazy)
|
|
{
|
|
struct xsc_cqe *cqe = get_sw_cqe(cq, cq->cons_index);
|
|
- if (cqe == NULL) {
|
|
+ int err = 0;
|
|
+
|
|
+ if (!cqe)
|
|
return CQ_EMPTY;
|
|
- }
|
|
- memset(wc, 0, sizeof(*wc));
|
|
|
|
++cq->cons_index;
|
|
|
|
@@ -472,7 +496,12 @@ static inline int xsc_poll_one(struct xsc_cq *cq,
|
|
* ownership bit.
|
|
*/
|
|
udma_from_device_barrier();
|
|
- return xsc_parse_cqe(cq, cqe, cur_rsc, wc, 0);
|
|
+ if (!lazy)
|
|
+ err = xsc_parse_cqe(cq, cqe, cur_rsc, wc);
|
|
+ else
|
|
+ err = xsc_parse_cqe_lazy(cq, cqe);
|
|
+
|
|
+ return err;
|
|
}
|
|
|
|
static inline void gen_flush_err_cqe(struct xsc_err_state_qp_node *err_node,
|
|
@@ -500,10 +529,12 @@ static inline void gen_flush_err_cqe(struct xsc_err_state_qp_node *err_node,
|
|
|
|
wc->qp_num = qp_id;
|
|
wc->status = IBV_WC_WR_FLUSH_ERR;
|
|
- wc->vendor_err = XSC_ERR_CODE_FLUSH;
|
|
+ wc->vendor_err = XSC_ANDES_ERR_CODE_FLUSH;
|
|
wc->wr_id = wq->wrid[idx];
|
|
wq->tail++;
|
|
wq->flush_wqe_cnt--;
|
|
+ if (err_node->is_sq)
|
|
+ wq->need_flush[idx] = 0;
|
|
}
|
|
|
|
static inline int xsc_generate_flush_err_cqe(struct ibv_cq *ibcq,
|
|
@@ -578,9 +609,14 @@ static inline int poll_cq(struct ibv_cq *ibcq, int ne, struct ibv_wc *wc)
|
|
int err = CQ_OK;
|
|
uint32_t next_cid = cq->cons_index;
|
|
|
|
+ if (cq->stall_enable && cq->stall_next_poll) {
|
|
+ cq->stall_next_poll = 0;
|
|
+ xsc_stall_poll_cq();
|
|
+ }
|
|
+
|
|
xsc_spin_lock(&cq->lock);
|
|
for (npolled = 0; npolled < ne; ++npolled) {
|
|
- err = xsc_poll_one(cq, &rsc, wc + npolled);
|
|
+ err = xsc_poll_one(cq, &rsc, wc + npolled, 0);
|
|
if (err != CQ_OK)
|
|
break;
|
|
}
|
|
@@ -596,677 +632,148 @@ static inline int poll_cq(struct ibv_cq *ibcq, int ne, struct ibv_wc *wc)
|
|
update_cons_index(cq);
|
|
xsc_spin_unlock(&cq->lock);
|
|
|
|
- return err == CQ_POLL_ERR ? err : npolled;
|
|
-}
|
|
-
|
|
-enum polling_mode {
|
|
- POLLING_MODE_NO_STALL,
|
|
- POLLING_MODE_STALL,
|
|
- POLLING_MODE_STALL_ADAPTIVE
|
|
-};
|
|
+ if (cq->stall_enable && err == CQ_EMPTY)
|
|
+ cq->stall_next_poll = 1;
|
|
|
|
-static inline void _xsc_end_poll(struct ibv_cq_ex *ibcq,
|
|
- int lock, enum polling_mode stall)
|
|
- ALWAYS_INLINE;
|
|
-static inline void _xsc_end_poll(struct ibv_cq_ex *ibcq,
|
|
- int lock, enum polling_mode stall)
|
|
-{
|
|
- struct xsc_cq *cq = to_xcq(ibv_cq_ex_to_cq(ibcq));
|
|
-
|
|
- update_cons_index(cq);
|
|
-
|
|
- if (lock)
|
|
- xsc_spin_unlock(&cq->lock);
|
|
-
|
|
- if (stall) {
|
|
- if (stall == POLLING_MODE_STALL_ADAPTIVE) {
|
|
- if (!(cq->flags & XSC_CQ_FLAGS_FOUND_CQES)) {
|
|
- cq->stall_cycles = max(cq->stall_cycles - xsc_stall_cq_dec_step,
|
|
- xsc_stall_cq_poll_min);
|
|
- xsc_get_cycles(&cq->stall_last_count);
|
|
- } else if (cq->flags & XSC_CQ_FLAGS_EMPTY_DURING_POLL) {
|
|
- cq->stall_cycles = min(cq->stall_cycles + xsc_stall_cq_inc_step,
|
|
- xsc_stall_cq_poll_max);
|
|
- xsc_get_cycles(&cq->stall_last_count);
|
|
- } else {
|
|
- cq->stall_cycles = max(cq->stall_cycles - xsc_stall_cq_dec_step,
|
|
- xsc_stall_cq_poll_min);
|
|
- cq->stall_last_count = 0;
|
|
- }
|
|
- } else if (!(cq->flags & XSC_CQ_FLAGS_FOUND_CQES)) {
|
|
- cq->stall_next_poll = 1;
|
|
- }
|
|
-
|
|
- cq->flags &= ~(XSC_CQ_FLAGS_FOUND_CQES | XSC_CQ_FLAGS_EMPTY_DURING_POLL);
|
|
- }
|
|
+ return err == CQ_POLL_ERR ? err : npolled;
|
|
}
|
|
|
|
-static inline int xsc_start_poll(struct ibv_cq_ex *ibcq, struct ibv_poll_cq_attr *attr,
|
|
- int lock, enum polling_mode stall,
|
|
- int cqe_version, int clock_update)
|
|
- ALWAYS_INLINE;
|
|
-static inline int xsc_start_poll(struct ibv_cq_ex *ibcq, struct ibv_poll_cq_attr *attr,
|
|
- int lock, enum polling_mode stall,
|
|
- int cqe_version, int clock_update)
|
|
+int xsc_poll_cq(struct ibv_cq *ibcq, int ne, struct ibv_wc *wc)
|
|
{
|
|
- struct xsc_cq *cq = to_xcq(ibv_cq_ex_to_cq(ibcq));
|
|
- struct xsc_cqe64 *cqe64;
|
|
- void *cqe;
|
|
- int err;
|
|
-
|
|
- if (unlikely(attr->comp_mask))
|
|
- return EINVAL;
|
|
-
|
|
- if (stall) {
|
|
- if (stall == POLLING_MODE_STALL_ADAPTIVE) {
|
|
- if (cq->stall_last_count)
|
|
- xsc_stall_cycles_poll_cq(cq->stall_last_count + cq->stall_cycles);
|
|
- } else if (cq->stall_next_poll) {
|
|
- cq->stall_next_poll = 0;
|
|
- xsc_stall_poll_cq();
|
|
- }
|
|
- }
|
|
-
|
|
- if (lock)
|
|
- xsc_spin_lock(&cq->lock);
|
|
-
|
|
- cq->cur_rsc = NULL;
|
|
-
|
|
- err = xsc_get_next_cqe(cq, &cqe64, &cqe);
|
|
- if (err == CQ_EMPTY) {
|
|
- if (lock)
|
|
- xsc_spin_unlock(&cq->lock);
|
|
-
|
|
- if (stall) {
|
|
- if (stall == POLLING_MODE_STALL_ADAPTIVE) {
|
|
- cq->stall_cycles = max(cq->stall_cycles - xsc_stall_cq_dec_step,
|
|
- xsc_stall_cq_poll_min);
|
|
- xsc_get_cycles(&cq->stall_last_count);
|
|
- } else {
|
|
- cq->stall_next_poll = 1;
|
|
- }
|
|
- }
|
|
-
|
|
- return ENOENT;
|
|
- }
|
|
-
|
|
- if (stall)
|
|
- cq->flags |= XSC_CQ_FLAGS_FOUND_CQES;
|
|
-
|
|
- err = xsc_parse_lazy_cqe(cq, cqe64, cqe, cqe_version);
|
|
- if (lock && err)
|
|
- xsc_spin_unlock(&cq->lock);
|
|
-
|
|
- if (stall && err) {
|
|
- if (stall == POLLING_MODE_STALL_ADAPTIVE) {
|
|
- cq->stall_cycles = max(cq->stall_cycles - xsc_stall_cq_dec_step,
|
|
- xsc_stall_cq_poll_min);
|
|
- cq->stall_last_count = 0;
|
|
- }
|
|
-
|
|
- cq->flags &= ~(XSC_CQ_FLAGS_FOUND_CQES);
|
|
-
|
|
- goto out;
|
|
- }
|
|
-
|
|
- if (clock_update && !err)
|
|
- err = xscdv_get_clock_info(ibcq->context, &cq->last_clock_info);
|
|
-
|
|
-out:
|
|
- return err;
|
|
+ return poll_cq(ibcq, ne, wc);
|
|
}
|
|
|
|
-static inline int xsc_next_poll(struct ibv_cq_ex *ibcq,
|
|
- enum polling_mode stall, int cqe_version)
|
|
+static inline int xsc_start_poll(struct ibv_cq_ex *ibcq,
|
|
+ struct ibv_poll_cq_attr *attr)
|
|
ALWAYS_INLINE;
|
|
-static inline int xsc_next_poll(struct ibv_cq_ex *ibcq,
|
|
- enum polling_mode stall,
|
|
- int cqe_version)
|
|
+static inline int xsc_start_poll(struct ibv_cq_ex *ibcq,
|
|
+ struct ibv_poll_cq_attr *attr)
|
|
{
|
|
struct xsc_cq *cq = to_xcq(ibv_cq_ex_to_cq(ibcq));
|
|
- struct xsc_cqe64 *cqe64;
|
|
- void *cqe;
|
|
int err;
|
|
|
|
- err = xsc_get_next_cqe(cq, &cqe64, &cqe);
|
|
- if (err == CQ_EMPTY) {
|
|
- if (stall == POLLING_MODE_STALL_ADAPTIVE)
|
|
- cq->flags |= XSC_CQ_FLAGS_EMPTY_DURING_POLL;
|
|
-
|
|
- return ENOENT;
|
|
- }
|
|
-
|
|
- return xsc_parse_lazy_cqe(cq, cqe64, cqe, cqe_version);
|
|
-}
|
|
-
|
|
-static inline int xsc_next_poll_adaptive_v0(struct ibv_cq_ex *ibcq)
|
|
-{
|
|
- return xsc_next_poll(ibcq, POLLING_MODE_STALL_ADAPTIVE, 0);
|
|
-}
|
|
-
|
|
-static inline int xsc_next_poll_adaptive_v1(struct ibv_cq_ex *ibcq)
|
|
-{
|
|
- return xsc_next_poll(ibcq, POLLING_MODE_STALL_ADAPTIVE, 1);
|
|
-}
|
|
-
|
|
-static inline int xsc_next_poll_v0(struct ibv_cq_ex *ibcq)
|
|
-{
|
|
- return xsc_next_poll(ibcq, 0, 0);
|
|
-}
|
|
-
|
|
-static inline int xsc_next_poll_v1(struct ibv_cq_ex *ibcq)
|
|
-{
|
|
- return xsc_next_poll(ibcq, 0, 1);
|
|
-}
|
|
-
|
|
-static inline int xsc_start_poll_v0(struct ibv_cq_ex *ibcq,
|
|
- struct ibv_poll_cq_attr *attr)
|
|
-{
|
|
- return xsc_start_poll(ibcq, attr, 0, 0, 0, 0);
|
|
-}
|
|
-
|
|
-static inline int xsc_start_poll_v1(struct ibv_cq_ex *ibcq,
|
|
- struct ibv_poll_cq_attr *attr)
|
|
-{
|
|
- return xsc_start_poll(ibcq, attr, 0, 0, 1, 0);
|
|
-}
|
|
-
|
|
-static inline int xsc_start_poll_v0_lock(struct ibv_cq_ex *ibcq,
|
|
- struct ibv_poll_cq_attr *attr)
|
|
-{
|
|
- return xsc_start_poll(ibcq, attr, 1, 0, 0, 0);
|
|
-}
|
|
-
|
|
-static inline int xsc_start_poll_v1_lock(struct ibv_cq_ex *ibcq,
|
|
- struct ibv_poll_cq_attr *attr)
|
|
-{
|
|
- return xsc_start_poll(ibcq, attr, 1, 0, 1, 0);
|
|
-}
|
|
-
|
|
-static inline int xsc_start_poll_adaptive_stall_v0_lock(struct ibv_cq_ex *ibcq,
|
|
- struct ibv_poll_cq_attr *attr)
|
|
-{
|
|
- return xsc_start_poll(ibcq, attr, 1, POLLING_MODE_STALL_ADAPTIVE, 0, 0);
|
|
-}
|
|
-
|
|
-static inline int xsc_start_poll_stall_v0_lock(struct ibv_cq_ex *ibcq,
|
|
- struct ibv_poll_cq_attr *attr)
|
|
-{
|
|
- return xsc_start_poll(ibcq, attr, 1, POLLING_MODE_STALL, 0, 0);
|
|
-}
|
|
-
|
|
-static inline int xsc_start_poll_adaptive_stall_v1_lock(struct ibv_cq_ex *ibcq,
|
|
- struct ibv_poll_cq_attr *attr)
|
|
-{
|
|
- return xsc_start_poll(ibcq, attr, 1, POLLING_MODE_STALL_ADAPTIVE, 1, 0);
|
|
-}
|
|
-
|
|
-static inline int xsc_start_poll_stall_v1_lock(struct ibv_cq_ex *ibcq,
|
|
- struct ibv_poll_cq_attr *attr)
|
|
-{
|
|
- return xsc_start_poll(ibcq, attr, 1, POLLING_MODE_STALL, 1, 0);
|
|
-}
|
|
-
|
|
-static inline int xsc_start_poll_stall_v0(struct ibv_cq_ex *ibcq,
|
|
- struct ibv_poll_cq_attr *attr)
|
|
-{
|
|
- return xsc_start_poll(ibcq, attr, 0, POLLING_MODE_STALL, 0, 0);
|
|
-}
|
|
-
|
|
-static inline int xsc_start_poll_adaptive_stall_v0(struct ibv_cq_ex *ibcq,
|
|
- struct ibv_poll_cq_attr *attr)
|
|
-{
|
|
- return xsc_start_poll(ibcq, attr, 0, POLLING_MODE_STALL_ADAPTIVE, 0, 0);
|
|
-}
|
|
-
|
|
-static inline int xsc_start_poll_adaptive_stall_v1(struct ibv_cq_ex *ibcq,
|
|
- struct ibv_poll_cq_attr *attr)
|
|
-{
|
|
- return xsc_start_poll(ibcq, attr, 0, POLLING_MODE_STALL_ADAPTIVE, 1, 0);
|
|
-}
|
|
-
|
|
-static inline int xsc_start_poll_stall_v1(struct ibv_cq_ex *ibcq,
|
|
- struct ibv_poll_cq_attr *attr)
|
|
-{
|
|
- return xsc_start_poll(ibcq, attr, 0, POLLING_MODE_STALL, 1, 0);
|
|
-}
|
|
-
|
|
-static inline int xsc_start_poll_v0_lock_clock_update(struct ibv_cq_ex *ibcq,
|
|
- struct ibv_poll_cq_attr *attr)
|
|
-{
|
|
- return xsc_start_poll(ibcq, attr, 1, 0, 0, 1);
|
|
-}
|
|
-
|
|
-static inline int xsc_start_poll_v1_lock_clock_update(struct ibv_cq_ex *ibcq,
|
|
- struct ibv_poll_cq_attr *attr)
|
|
-{
|
|
- return xsc_start_poll(ibcq, attr, 1, 0, 1, 1);
|
|
-}
|
|
-
|
|
-static inline int xsc_start_poll_v1_clock_update(struct ibv_cq_ex *ibcq,
|
|
- struct ibv_poll_cq_attr *attr)
|
|
-{
|
|
- return xsc_start_poll(ibcq, attr, 0, 0, 1, 1);
|
|
-}
|
|
-
|
|
-static inline int xsc_start_poll_v0_clock_update(struct ibv_cq_ex *ibcq,
|
|
- struct ibv_poll_cq_attr *attr)
|
|
-{
|
|
- return xsc_start_poll(ibcq, attr, 0, 0, 0, 1);
|
|
-}
|
|
-
|
|
-static inline int xsc_start_poll_stall_v1_lock_clock_update(struct ibv_cq_ex *ibcq,
|
|
- struct ibv_poll_cq_attr *attr)
|
|
-{
|
|
- return xsc_start_poll(ibcq, attr, 1, POLLING_MODE_STALL, 1, 1);
|
|
-}
|
|
-
|
|
-static inline int xsc_start_poll_stall_v0_lock_clock_update(struct ibv_cq_ex *ibcq,
|
|
- struct ibv_poll_cq_attr *attr)
|
|
-{
|
|
- return xsc_start_poll(ibcq, attr, 1, POLLING_MODE_STALL, 0, 1);
|
|
-}
|
|
-
|
|
-static inline int xsc_start_poll_stall_v1_clock_update(struct ibv_cq_ex *ibcq,
|
|
- struct ibv_poll_cq_attr *attr)
|
|
-{
|
|
- return xsc_start_poll(ibcq, attr, 0, POLLING_MODE_STALL, 1, 1);
|
|
-}
|
|
-
|
|
-static inline int xsc_start_poll_stall_v0_clock_update(struct ibv_cq_ex *ibcq,
|
|
- struct ibv_poll_cq_attr *attr)
|
|
-{
|
|
- return xsc_start_poll(ibcq, attr, 0, POLLING_MODE_STALL, 0, 1);
|
|
-}
|
|
-
|
|
-static inline int xsc_start_poll_adaptive_stall_v0_lock_clock_update(struct ibv_cq_ex *ibcq,
|
|
- struct ibv_poll_cq_attr *attr)
|
|
-{
|
|
- return xsc_start_poll(ibcq, attr, 1, POLLING_MODE_STALL_ADAPTIVE, 0, 1);
|
|
-}
|
|
-
|
|
-static inline int xsc_start_poll_adaptive_stall_v1_lock_clock_update(struct ibv_cq_ex *ibcq,
|
|
- struct ibv_poll_cq_attr *attr)
|
|
-{
|
|
- return xsc_start_poll(ibcq, attr, 1, POLLING_MODE_STALL_ADAPTIVE, 1, 1);
|
|
-}
|
|
-
|
|
-static inline int xsc_start_poll_adaptive_stall_v0_clock_update(struct ibv_cq_ex *ibcq,
|
|
- struct ibv_poll_cq_attr *attr)
|
|
-{
|
|
- return xsc_start_poll(ibcq, attr, 0, POLLING_MODE_STALL_ADAPTIVE, 0, 1);
|
|
-}
|
|
-
|
|
-static inline int xsc_start_poll_adaptive_stall_v1_clock_update(struct ibv_cq_ex *ibcq,
|
|
- struct ibv_poll_cq_attr *attr)
|
|
-{
|
|
- return xsc_start_poll(ibcq, attr, 0, POLLING_MODE_STALL_ADAPTIVE, 1, 1);
|
|
-}
|
|
-
|
|
-static inline void xsc_end_poll_adaptive_stall_lock(struct ibv_cq_ex *ibcq)
|
|
-{
|
|
- _xsc_end_poll(ibcq, 1, POLLING_MODE_STALL_ADAPTIVE);
|
|
-}
|
|
-
|
|
-static inline void xsc_end_poll_stall_lock(struct ibv_cq_ex *ibcq)
|
|
-{
|
|
- _xsc_end_poll(ibcq, 1, POLLING_MODE_STALL);
|
|
-}
|
|
-
|
|
-static inline void xsc_end_poll_adaptive_stall(struct ibv_cq_ex *ibcq)
|
|
-{
|
|
- _xsc_end_poll(ibcq, 0, POLLING_MODE_STALL_ADAPTIVE);
|
|
-}
|
|
+ xsc_spin_lock(&cq->lock);
|
|
+ err = xsc_poll_one(cq, NULL, NULL, 1);
|
|
+ if (err == CQ_EMPTY)
|
|
+ xsc_spin_unlock(&cq->lock);
|
|
|
|
-static inline void xsc_end_poll_stall(struct ibv_cq_ex *ibcq)
|
|
-{
|
|
- _xsc_end_poll(ibcq, 0, POLLING_MODE_STALL);
|
|
+ return (err == CQ_EMPTY) ? ENOENT : err;
|
|
}
|
|
|
|
static inline void xsc_end_poll(struct ibv_cq_ex *ibcq)
|
|
-{
|
|
- _xsc_end_poll(ibcq, 0, 0);
|
|
-}
|
|
-
|
|
-static inline void xsc_end_poll_lock(struct ibv_cq_ex *ibcq)
|
|
-{
|
|
- _xsc_end_poll(ibcq, 1, 0);
|
|
-}
|
|
-
|
|
-int xsc_poll_cq(struct ibv_cq *ibcq, int ne, struct ibv_wc *wc)
|
|
-{
|
|
- return poll_cq(ibcq, ne, wc);
|
|
-}
|
|
-
|
|
-static inline enum ibv_wc_opcode xsc_cq_read_wc_opcode(struct ibv_cq_ex *ibcq)
|
|
-{
|
|
- struct xsc_cq *cq = to_xcq(ibv_cq_ex_to_cq(ibcq));
|
|
-
|
|
- switch (xscdv_get_cqe_opcode(cq->cqe64)) {
|
|
- case XSC_CQE_RESP_WR_IMM:
|
|
- return IBV_WC_RECV_RDMA_WITH_IMM;
|
|
- case XSC_CQE_RESP_SEND:
|
|
- case XSC_CQE_RESP_SEND_IMM:
|
|
- case XSC_CQE_RESP_SEND_INV:
|
|
- if (unlikely(cq->cqe64->app == XSC_CQE_APP_TAG_MATCHING)) {
|
|
- switch (cq->cqe64->app_op) {
|
|
- case XSC_CQE_APP_OP_TM_CONSUMED_MSG_SW_RDNV:
|
|
- case XSC_CQE_APP_OP_TM_CONSUMED_MSG:
|
|
- case XSC_CQE_APP_OP_TM_CONSUMED_SW_RDNV:
|
|
- case XSC_CQE_APP_OP_TM_EXPECTED:
|
|
- case XSC_CQE_APP_OP_TM_UNEXPECTED:
|
|
- return IBV_WC_TM_RECV;
|
|
- case XSC_CQE_APP_OP_TM_NO_TAG:
|
|
- return IBV_WC_TM_NO_TAG;
|
|
- }
|
|
- }
|
|
- return IBV_WC_RECV;
|
|
- case XSC_CQE_NO_PACKET:
|
|
- switch (cq->cqe64->app_op) {
|
|
- case XSC_CQE_APP_OP_TM_REMOVE:
|
|
- return IBV_WC_TM_DEL;
|
|
- case XSC_CQE_APP_OP_TM_APPEND:
|
|
- return IBV_WC_TM_ADD;
|
|
- case XSC_CQE_APP_OP_TM_NOOP:
|
|
- return IBV_WC_TM_SYNC;
|
|
- case XSC_CQE_APP_OP_TM_CONSUMED:
|
|
- return IBV_WC_TM_RECV;
|
|
- }
|
|
- break;
|
|
- case XSC_CQE_REQ:
|
|
- switch (be32toh(cq->cqe64->sop_drop_qpn) >> 24) {
|
|
- case XSC_OPCODE_RDMA_WRITE_IMM:
|
|
- case XSC_OPCODE_RDMA_WRITE:
|
|
- return IBV_WC_RDMA_WRITE;
|
|
- case XSC_OPCODE_SEND_IMM:
|
|
- case XSC_OPCODE_SEND:
|
|
- case XSC_OPCODE_SEND_INVAL:
|
|
- return IBV_WC_SEND;
|
|
- case XSC_OPCODE_RDMA_READ:
|
|
- return IBV_WC_RDMA_READ;
|
|
- case XSC_OPCODE_ATOMIC_CS:
|
|
- return IBV_WC_COMP_SWAP;
|
|
- case XSC_OPCODE_ATOMIC_FA:
|
|
- return IBV_WC_FETCH_ADD;
|
|
- case XSC_OPCODE_UMR:
|
|
- return cq->umr_opcode;
|
|
- case XSC_OPCODE_TSO:
|
|
- return IBV_WC_TSO;
|
|
- }
|
|
- }
|
|
-
|
|
- return 0;
|
|
-}
|
|
-
|
|
-static inline uint32_t xsc_cq_read_wc_qp_num(struct ibv_cq_ex *ibcq)
|
|
+ ALWAYS_INLINE;
|
|
+static inline void xsc_end_poll(struct ibv_cq_ex *ibcq)
|
|
{
|
|
struct xsc_cq *cq = to_xcq(ibv_cq_ex_to_cq(ibcq));
|
|
|
|
- return be32toh(cq->cqe64->sop_drop_qpn) & 0xffffff;
|
|
+ udma_to_device_barrier();
|
|
+ update_cons_index(cq);
|
|
+ xsc_spin_unlock(&cq->lock);
|
|
}
|
|
|
|
-static inline unsigned int xsc_cq_read_wc_flags(struct ibv_cq_ex *ibcq)
|
|
+static inline int xsc_next_poll(struct ibv_cq_ex *ibcq)
|
|
+ ALWAYS_INLINE;
|
|
+static inline int xsc_next_poll(struct ibv_cq_ex *ibcq)
|
|
{
|
|
struct xsc_cq *cq = to_xcq(ibv_cq_ex_to_cq(ibcq));
|
|
- int wc_flags = 0;
|
|
-
|
|
- if (cq->flags & XSC_CQ_FLAGS_RX_CSUM_VALID)
|
|
- wc_flags = get_csum_ok(cq->cqe64);
|
|
-
|
|
- switch (xscdv_get_cqe_opcode(cq->cqe64)) {
|
|
- case XSC_CQE_RESP_WR_IMM:
|
|
- case XSC_CQE_RESP_SEND_IMM:
|
|
- wc_flags |= IBV_WC_WITH_IMM;
|
|
- break;
|
|
- case XSC_CQE_RESP_SEND_INV:
|
|
- wc_flags |= IBV_WC_WITH_INV;
|
|
- break;
|
|
- }
|
|
-
|
|
- if (cq->flags & XSC_CQ_FLAGS_TM_SYNC_REQ)
|
|
- wc_flags |= IBV_WC_TM_SYNC_REQ;
|
|
+ int err;
|
|
|
|
- if (unlikely(cq->cqe64->app == XSC_CQE_APP_TAG_MATCHING)) {
|
|
- switch (cq->cqe64->app_op) {
|
|
- case XSC_CQE_APP_OP_TM_CONSUMED_MSG_SW_RDNV:
|
|
- case XSC_CQE_APP_OP_TM_CONSUMED_MSG:
|
|
- case XSC_CQE_APP_OP_TM_MSG_COMPLETION_CANCELED:
|
|
- /* Full completion */
|
|
- wc_flags |= (IBV_WC_TM_MATCH | IBV_WC_TM_DATA_VALID);
|
|
- break;
|
|
- case XSC_CQE_APP_OP_TM_CONSUMED_SW_RDNV:
|
|
- case XSC_CQE_APP_OP_TM_CONSUMED: /* First completion */
|
|
- wc_flags |= IBV_WC_TM_MATCH;
|
|
- break;
|
|
- case XSC_CQE_APP_OP_TM_EXPECTED: /* Second completion */
|
|
- wc_flags |= IBV_WC_TM_DATA_VALID;
|
|
- break;
|
|
- }
|
|
- }
|
|
+ err = xsc_poll_one(cq, NULL, NULL, 1);
|
|
|
|
- wc_flags |= ((be32toh(cq->cqe64->flags_rqpn) >> 28) & 3) ? IBV_WC_GRH : 0;
|
|
- return wc_flags;
|
|
+ return (err == CQ_EMPTY) ? ENOENT : err;
|
|
}
|
|
|
|
-static inline uint32_t xsc_cq_read_wc_byte_len(struct ibv_cq_ex *ibcq)
|
|
+static inline enum ibv_wc_opcode xsc_wc_read_opcode(struct ibv_cq_ex *ibcq)
|
|
{
|
|
- struct xsc_cq *cq = to_xcq(ibv_cq_ex_to_cq(ibcq));
|
|
+ struct xsc_cqe *cqe = to_xcq(ibv_cq_ex_to_cq(ibcq))->cqe;
|
|
+ struct xsc_context *xctx = to_xctx(ibv_cq_ex_to_cq(ibcq)->context);
|
|
+ uint8_t opcode = xsc_hw_get_cqe_msg_opcode(xctx->device_id, cqe);
|
|
|
|
- return be32toh(cq->cqe64->byte_cnt);
|
|
+ return xsc_cqe_opcode[opcode];
|
|
}
|
|
|
|
-static inline uint32_t xsc_cq_read_wc_vendor_err(struct ibv_cq_ex *ibcq)
|
|
+static inline uint32_t xsc_wc_read_qp_num(struct ibv_cq_ex *ibcq)
|
|
{
|
|
- struct xsc_cq *cq = to_xcq(ibv_cq_ex_to_cq(ibcq));
|
|
- struct xsc_err_cqe *ecqe = (struct xsc_err_cqe *)cq->cqe64;
|
|
+ struct xsc_cqe *cqe = to_xcq(ibv_cq_ex_to_cq(ibcq))->cqe;
|
|
|
|
- return ecqe->vendor_err_synd;
|
|
+ return le32toh(cqe->qp_id);
|
|
}
|
|
|
|
-static inline __be32 xsc_cq_read_wc_imm_data(struct ibv_cq_ex *ibcq)
|
|
+static inline unsigned int xsc_wc_read_flags(struct ibv_cq_ex *ibcq)
|
|
{
|
|
- struct xsc_cq *cq = to_xcq(ibv_cq_ex_to_cq(ibcq));
|
|
+ struct xsc_cqe *cqe = to_xcq(ibv_cq_ex_to_cq(ibcq))->cqe;
|
|
+ struct xsc_context *xctx = to_xctx(ibv_cq_ex_to_cq(ibcq)->context);
|
|
+ uint8_t opcode = xsc_hw_get_cqe_msg_opcode(xctx->device_id, cqe);
|
|
|
|
- switch (xscdv_get_cqe_opcode(cq->cqe64)) {
|
|
- case XSC_CQE_RESP_SEND_INV:
|
|
- /* This is returning invalidate_rkey which is in host order, see
|
|
- * ibv_wc_read_invalidated_rkey
|
|
- */
|
|
- return (__force __be32)be32toh(cq->cqe64->imm_inval_pkey);
|
|
+ switch (opcode) {
|
|
+ case XSC_OPCODE_RDMA_REQ_SEND_IMMDT:
|
|
+ case XSC_OPCODE_RDMA_REQ_WRITE_IMMDT:
|
|
+ case XSC_OPCODE_RDMA_RSP_RECV_IMMDT:
|
|
+ case XSC_OPCODE_RDMA_RSP_WRITE_IMMDT:
|
|
+ return IBV_WC_WITH_IMM;
|
|
default:
|
|
- return cq->cqe64->imm_inval_pkey;
|
|
+ return 0;
|
|
}
|
|
}
|
|
|
|
-static inline uint32_t xsc_cq_read_wc_slid(struct ibv_cq_ex *ibcq)
|
|
+static inline uint32_t xsc_wc_read_byte_len(struct ibv_cq_ex *ibcq)
|
|
{
|
|
- struct xsc_cq *cq = to_xcq(ibv_cq_ex_to_cq(ibcq));
|
|
+ struct xsc_cqe *cqe = to_xcq(ibv_cq_ex_to_cq(ibcq))->cqe;
|
|
|
|
- return (uint32_t)be16toh(cq->cqe64->slid);
|
|
+ return le32toh(cqe->msg_len);
|
|
}
|
|
|
|
-static inline uint8_t xsc_cq_read_wc_sl(struct ibv_cq_ex *ibcq)
|
|
+static inline uint32_t xsc_wc_read_vendor_err(struct ibv_cq_ex *ibcq)
|
|
{
|
|
- struct xsc_cq *cq = to_xcq(ibv_cq_ex_to_cq(ibcq));
|
|
+ struct xsc_cqe *cqe = to_xcq(ibv_cq_ex_to_cq(ibcq))->cqe;
|
|
+ struct xsc_context *xctx = to_xctx(ibv_cq_ex_to_cq(ibcq)->context);
|
|
|
|
- return (be32toh(cq->cqe64->flags_rqpn) >> 24) & 0xf;
|
|
+ return xsc_hw_get_cqe_err_code(xctx->device_id, cqe);
|
|
}
|
|
|
|
-static inline uint32_t xsc_cq_read_wc_src_qp(struct ibv_cq_ex *ibcq)
|
|
+static inline __be32 xsc_wc_read_imm_data(struct ibv_cq_ex *ibcq)
|
|
{
|
|
- struct xsc_cq *cq = to_xcq(ibv_cq_ex_to_cq(ibcq));
|
|
+ struct xsc_cqe *cqe = to_xcq(ibv_cq_ex_to_cq(ibcq))->cqe;
|
|
+ __be32 imm_data;
|
|
|
|
- return be32toh(cq->cqe64->flags_rqpn) & 0xffffff;
|
|
-}
|
|
-
|
|
-static inline uint8_t xsc_cq_read_wc_dlid_path_bits(struct ibv_cq_ex *ibcq)
|
|
-{
|
|
- struct xsc_cq *cq = to_xcq(ibv_cq_ex_to_cq(ibcq));
|
|
+ WR_BE_32(imm_data, RD_LE_32(cqe->imm_data));
|
|
|
|
- return cq->cqe64->ml_path & 0x7f;
|
|
+ return imm_data;
|
|
}
|
|
|
|
-static inline uint64_t xsc_cq_read_wc_completion_ts(struct ibv_cq_ex *ibcq)
|
|
+static inline uint64_t xsc_wc_read_completion_ts(struct ibv_cq_ex *ibcq)
|
|
{
|
|
- struct xsc_cq *cq = to_xcq(ibv_cq_ex_to_cq(ibcq));
|
|
+ struct xsc_cqe *cqe = to_xcq(ibv_cq_ex_to_cq(ibcq))->cqe;
|
|
|
|
- return be64toh(cq->cqe64->timestamp);
|
|
+ return le64toh(cqe->ts);
|
|
}
|
|
|
|
-static inline uint64_t
|
|
-xsc_cq_read_wc_completion_wallclock_ns(struct ibv_cq_ex *ibcq)
|
|
+void xsc_cq_fill_pfns(struct xsc_cq *cq, const struct ibv_cq_init_attr_ex *cq_attr)
|
|
{
|
|
- struct xsc_cq *cq = to_xcq(ibv_cq_ex_to_cq(ibcq));
|
|
-
|
|
- return xscdv_ts_to_ns(&cq->last_clock_info,
|
|
- xsc_cq_read_wc_completion_ts(ibcq));
|
|
-}
|
|
|
|
-static inline uint16_t xsc_cq_read_wc_cvlan(struct ibv_cq_ex *ibcq)
|
|
-{
|
|
- struct xsc_cq *cq = to_xcq(ibv_cq_ex_to_cq(ibcq));
|
|
+ cq->verbs_cq.cq_ex.start_poll = xsc_start_poll;
|
|
+ cq->verbs_cq.cq_ex.next_poll = xsc_next_poll;
|
|
+ cq->verbs_cq.cq_ex.end_poll = xsc_end_poll;
|
|
|
|
- return be16toh(cq->cqe64->vlan_info);
|
|
-}
|
|
-
|
|
-static inline uint32_t xsc_cq_read_flow_tag(struct ibv_cq_ex *ibcq)
|
|
-{
|
|
- struct xsc_cq *cq = to_xcq(ibv_cq_ex_to_cq(ibcq));
|
|
-
|
|
- return be32toh(cq->cqe64->sop_drop_qpn) & XSC_FLOW_TAG_MASK;
|
|
-}
|
|
-
|
|
-static inline void xsc_cq_read_wc_tm_info(struct ibv_cq_ex *ibcq,
|
|
- struct ibv_wc_tm_info *tm_info)
|
|
-{
|
|
- struct xsc_cq *cq = to_xcq(ibv_cq_ex_to_cq(ibcq));
|
|
-
|
|
- tm_info->tag = be64toh(cq->cqe64->tmh.tag);
|
|
- tm_info->priv = be32toh(cq->cqe64->tmh.app_ctx);
|
|
-}
|
|
-
|
|
-#define BIT(i) (1UL << (i))
|
|
-
|
|
-#define SINGLE_THREADED BIT(0)
|
|
-#define STALL BIT(1)
|
|
-#define V1 BIT(2)
|
|
-#define ADAPTIVE BIT(3)
|
|
-#define CLOCK_UPDATE BIT(4)
|
|
-
|
|
-#define xsc_start_poll_name(cqe_ver, lock, stall, adaptive, clock_update) \
|
|
- xsc_start_poll##adaptive##stall##cqe_ver##lock##clock_update
|
|
-#define xsc_next_poll_name(cqe_ver, adaptive) \
|
|
- xsc_next_poll##adaptive##cqe_ver
|
|
-#define xsc_end_poll_name(lock, stall, adaptive) \
|
|
- xsc_end_poll##adaptive##stall##lock
|
|
-
|
|
-#define POLL_FN_ENTRY(cqe_ver, lock, stall, adaptive, clock_update) { \
|
|
- .start_poll = &xsc_start_poll_name(cqe_ver, lock, stall, adaptive, clock_update), \
|
|
- .next_poll = &xsc_next_poll_name(cqe_ver, adaptive), \
|
|
- .end_poll = &xsc_end_poll_name(lock, stall, adaptive), \
|
|
- }
|
|
-
|
|
-static const struct op
|
|
-{
|
|
- int (*start_poll)(struct ibv_cq_ex *ibcq, struct ibv_poll_cq_attr *attr);
|
|
- int (*next_poll)(struct ibv_cq_ex *ibcq);
|
|
- void (*end_poll)(struct ibv_cq_ex *ibcq);
|
|
-} ops[ADAPTIVE + V1 + STALL + SINGLE_THREADED + CLOCK_UPDATE + 1] = {
|
|
- [V1] = POLL_FN_ENTRY(_v1, _lock, , ,),
|
|
- [0] = POLL_FN_ENTRY(_v0, _lock, , ,),
|
|
- [V1 | SINGLE_THREADED] = POLL_FN_ENTRY(_v1, , , , ),
|
|
- [SINGLE_THREADED] = POLL_FN_ENTRY(_v0, , , , ),
|
|
- [V1 | STALL] = POLL_FN_ENTRY(_v1, _lock, _stall, , ),
|
|
- [STALL] = POLL_FN_ENTRY(_v0, _lock, _stall, , ),
|
|
- [V1 | SINGLE_THREADED | STALL] = POLL_FN_ENTRY(_v1, , _stall, , ),
|
|
- [SINGLE_THREADED | STALL] = POLL_FN_ENTRY(_v0, , _stall, , ),
|
|
- [V1 | STALL | ADAPTIVE] = POLL_FN_ENTRY(_v1, _lock, _stall, _adaptive, ),
|
|
- [STALL | ADAPTIVE] = POLL_FN_ENTRY(_v0, _lock, _stall, _adaptive, ),
|
|
- [V1 | SINGLE_THREADED | STALL | ADAPTIVE] = POLL_FN_ENTRY(_v1, , _stall, _adaptive, ),
|
|
- [SINGLE_THREADED | STALL | ADAPTIVE] = POLL_FN_ENTRY(_v0, , _stall, _adaptive, ),
|
|
- [V1 | CLOCK_UPDATE] = POLL_FN_ENTRY(_v1, _lock, , , _clock_update),
|
|
- [0 | CLOCK_UPDATE] = POLL_FN_ENTRY(_v0, _lock, , , _clock_update),
|
|
- [V1 | SINGLE_THREADED | CLOCK_UPDATE] = POLL_FN_ENTRY(_v1, , , , _clock_update),
|
|
- [SINGLE_THREADED | CLOCK_UPDATE] = POLL_FN_ENTRY(_v0, , , , _clock_update),
|
|
- [V1 | STALL | CLOCK_UPDATE] = POLL_FN_ENTRY(_v1, _lock, _stall, , _clock_update),
|
|
- [STALL | CLOCK_UPDATE] = POLL_FN_ENTRY(_v0, _lock, _stall, , _clock_update),
|
|
- [V1 | SINGLE_THREADED | STALL | CLOCK_UPDATE] = POLL_FN_ENTRY(_v1, , _stall, , _clock_update),
|
|
- [SINGLE_THREADED | STALL | CLOCK_UPDATE] = POLL_FN_ENTRY(_v0, , _stall, , _clock_update),
|
|
- [V1 | STALL | ADAPTIVE | CLOCK_UPDATE] = POLL_FN_ENTRY(_v1, _lock, _stall, _adaptive, _clock_update),
|
|
- [STALL | ADAPTIVE | CLOCK_UPDATE] = POLL_FN_ENTRY(_v0, _lock, _stall, _adaptive, _clock_update),
|
|
- [V1 | SINGLE_THREADED | STALL | ADAPTIVE | CLOCK_UPDATE] = POLL_FN_ENTRY(_v1, , _stall, _adaptive, _clock_update),
|
|
- [SINGLE_THREADED | STALL | ADAPTIVE | CLOCK_UPDATE] = POLL_FN_ENTRY(_v0, , _stall, _adaptive, _clock_update),
|
|
-};
|
|
-
|
|
-int xsc_cq_fill_pfns(struct xsc_cq *cq,
|
|
- const struct ibv_cq_init_attr_ex *cq_attr,
|
|
- struct xsc_context *xctx)
|
|
-{
|
|
- const struct op *poll_ops = &ops[((cq->stall_enable && cq->stall_adaptive_enable) ? ADAPTIVE : 0) |
|
|
- (xctx->cqe_version ? V1 : 0) |
|
|
- (cq->flags & XSC_CQ_FLAGS_SINGLE_THREADED ?
|
|
- SINGLE_THREADED : 0) |
|
|
- (cq->stall_enable ? STALL : 0) |
|
|
- ((cq_attr->wc_flags & IBV_WC_EX_WITH_COMPLETION_TIMESTAMP_WALLCLOCK) ?
|
|
- CLOCK_UPDATE : 0)];
|
|
-
|
|
- cq->verbs_cq.cq_ex.start_poll = poll_ops->start_poll;
|
|
- cq->verbs_cq.cq_ex.next_poll = poll_ops->next_poll;
|
|
- cq->verbs_cq.cq_ex.end_poll = poll_ops->end_poll;
|
|
-
|
|
- cq->verbs_cq.cq_ex.read_opcode = xsc_cq_read_wc_opcode;
|
|
- cq->verbs_cq.cq_ex.read_vendor_err = xsc_cq_read_wc_vendor_err;
|
|
- cq->verbs_cq.cq_ex.read_wc_flags = xsc_cq_read_wc_flags;
|
|
+ cq->verbs_cq.cq_ex.read_opcode = xsc_wc_read_opcode;
|
|
+ cq->verbs_cq.cq_ex.read_vendor_err = xsc_wc_read_vendor_err;
|
|
+ cq->verbs_cq.cq_ex.read_wc_flags = xsc_wc_read_flags;
|
|
if (cq_attr->wc_flags & IBV_WC_EX_WITH_BYTE_LEN)
|
|
- cq->verbs_cq.cq_ex.read_byte_len = xsc_cq_read_wc_byte_len;
|
|
+ cq->verbs_cq.cq_ex.read_byte_len = xsc_wc_read_byte_len;
|
|
if (cq_attr->wc_flags & IBV_WC_EX_WITH_IMM)
|
|
- cq->verbs_cq.cq_ex.read_imm_data = xsc_cq_read_wc_imm_data;
|
|
+ cq->verbs_cq.cq_ex.read_imm_data = xsc_wc_read_imm_data;
|
|
if (cq_attr->wc_flags & IBV_WC_EX_WITH_QP_NUM)
|
|
- cq->verbs_cq.cq_ex.read_qp_num = xsc_cq_read_wc_qp_num;
|
|
- if (cq_attr->wc_flags & IBV_WC_EX_WITH_SRC_QP)
|
|
- cq->verbs_cq.cq_ex.read_src_qp = xsc_cq_read_wc_src_qp;
|
|
- if (cq_attr->wc_flags & IBV_WC_EX_WITH_SLID)
|
|
- cq->verbs_cq.cq_ex.read_slid = xsc_cq_read_wc_slid;
|
|
- if (cq_attr->wc_flags & IBV_WC_EX_WITH_SL)
|
|
- cq->verbs_cq.cq_ex.read_sl = xsc_cq_read_wc_sl;
|
|
- if (cq_attr->wc_flags & IBV_WC_EX_WITH_DLID_PATH_BITS)
|
|
- cq->verbs_cq.cq_ex.read_dlid_path_bits = xsc_cq_read_wc_dlid_path_bits;
|
|
+ cq->verbs_cq.cq_ex.read_qp_num = xsc_wc_read_qp_num;
|
|
if (cq_attr->wc_flags & IBV_WC_EX_WITH_COMPLETION_TIMESTAMP)
|
|
- cq->verbs_cq.cq_ex.read_completion_ts = xsc_cq_read_wc_completion_ts;
|
|
- if (cq_attr->wc_flags & IBV_WC_EX_WITH_CVLAN)
|
|
- cq->verbs_cq.cq_ex.read_cvlan = xsc_cq_read_wc_cvlan;
|
|
- if (cq_attr->wc_flags & IBV_WC_EX_WITH_FLOW_TAG)
|
|
- cq->verbs_cq.cq_ex.read_flow_tag = xsc_cq_read_flow_tag;
|
|
- if (cq_attr->wc_flags & IBV_WC_EX_WITH_TM_INFO)
|
|
- cq->verbs_cq.cq_ex.read_tm_info = xsc_cq_read_wc_tm_info;
|
|
- if (cq_attr->wc_flags & IBV_WC_EX_WITH_COMPLETION_TIMESTAMP_WALLCLOCK) {
|
|
- if (!xctx->clock_info_page)
|
|
- return EOPNOTSUPP;
|
|
- cq->verbs_cq.cq_ex.read_completion_wallclock_ns =
|
|
- xsc_cq_read_wc_completion_wallclock_ns;
|
|
- }
|
|
-
|
|
- return 0;
|
|
+ cq->verbs_cq.cq_ex.read_completion_ts = xsc_wc_read_completion_ts;
|
|
}
|
|
|
|
int xsc_arm_cq(struct ibv_cq *ibvcq, int solicited)
|
|
{
|
|
struct xsc_cq *cq = to_xcq(ibvcq);
|
|
- union xsc_db_data doorbell;
|
|
-
|
|
- doorbell.cqn = cq->cqn;
|
|
- doorbell.cq_next_cid = cq->cons_index;
|
|
- doorbell.solicited = !!solicited;
|
|
-
|
|
- /*
|
|
- * Make sure that the doorbell record in host memory is
|
|
- * written before ringing the doorbell via PCI WC MMIO.
|
|
- */
|
|
- mmio_wc_start();
|
|
-
|
|
- WR_REG(cq->armdb, doorbell.raw_data);
|
|
+ struct xsc_context *ctx = to_xctx(ibvcq->context);
|
|
|
|
- mmio_flush_writes();
|
|
+ xsc_hw_update_cq_db(ctx->device_id, cq->armdb, cq->cqn, cq->cons_index, solicited);
|
|
|
|
return 0;
|
|
}
|
|
diff --git a/providers/xscale/qp.c b/providers/xscale/qp.c
|
|
index 04e87e2..ea9ecb5 100644
|
|
--- a/providers/xscale/qp.c
|
|
+++ b/providers/xscale/qp.c
|
|
@@ -10,12 +10,12 @@
|
|
#include <string.h>
|
|
#include <errno.h>
|
|
#include <stdio.h>
|
|
-#include <util/mmio.h>
|
|
#include <util/compiler.h>
|
|
|
|
#include "xscale.h"
|
|
#include "wqe.h"
|
|
#include "xsc_hsi.h"
|
|
+#include "xsc_hw.h"
|
|
|
|
static const uint32_t xsc_ib_opcode[] = {
|
|
[IBV_WR_SEND] = XSC_MSG_OPCODE_SEND,
|
|
@@ -26,26 +26,21 @@ static const uint32_t xsc_ib_opcode[] = {
|
|
[IBV_WR_SEND_WITH_INV] = XSC_MSG_OPCODE_SEND,
|
|
};
|
|
|
|
-static void *get_recv_wqe(struct xsc_qp *qp, int n)
|
|
+static inline void *get_recv_wqe(struct xsc_qp *qp, int n)
|
|
{
|
|
return qp->rq_start + (n << qp->rq.wqe_shift);
|
|
}
|
|
|
|
-static void *get_wq_recv_wqe(struct xsc_rwq *rwq, int n)
|
|
+static inline void *get_wq_recv_wqe(struct xsc_rwq *rwq, int n)
|
|
{
|
|
return rwq->pbuff + (n << rwq->rq.wqe_shift);
|
|
}
|
|
|
|
-static void *get_seg_wqe(void *first, int n)
|
|
+static inline void *get_seg_wqe(void *first, int n)
|
|
{
|
|
return first + (n << XSC_BASE_WQE_SHIFT);
|
|
}
|
|
|
|
-void *xsc_get_send_wqe(struct xsc_qp *qp, int n)
|
|
-{
|
|
- return qp->sq_start + (n << qp->sq.wqe_shift);
|
|
-}
|
|
-
|
|
void xsc_init_rwq_indices(struct xsc_rwq *rwq)
|
|
{
|
|
rwq->rq.head = 0;
|
|
@@ -61,7 +56,7 @@ void xsc_init_qp_indices(struct xsc_qp *qp)
|
|
qp->sq.cur_post = 0;
|
|
}
|
|
|
|
-static int xsc_wq_overflow(struct xsc_wq *wq, int nreq, struct xsc_cq *cq)
|
|
+static inline int xsc_wq_overflow(struct xsc_wq *wq, int nreq, struct xsc_cq *cq)
|
|
{
|
|
unsigned cur;
|
|
|
|
@@ -76,65 +71,72 @@ static int xsc_wq_overflow(struct xsc_wq *wq, int nreq, struct xsc_cq *cq)
|
|
return cur + nreq >= wq->max_post;
|
|
}
|
|
|
|
-static inline void set_remote_addr_seg(struct xsc_wqe_data_seg *remote_seg,
|
|
- uint32_t msg_len, uint64_t remote_addr, uint32_t rkey)
|
|
+static inline void set_data_seg_with_value(struct xsc_qp *qp, struct xsc_wqe_data_seg *data_seg,
|
|
+ uint64_t addr, uint32_t key, uint32_t length)
|
|
{
|
|
- WR_LE_32(remote_seg->seg_len, msg_len);
|
|
- WR_LE_32(remote_seg->mkey, rkey);
|
|
- WR_LE_64(remote_seg->va, remote_addr);
|
|
+ struct xsc_context *ctx = to_xctx(qp->ibv_qp->context);
|
|
+
|
|
+ xsc_hw_set_data_seg(ctx->device_id, data_seg, addr, key, length);
|
|
}
|
|
|
|
-static void set_local_data_seg(struct xsc_wqe_data_seg *data_seg, struct ibv_sge *sg)
|
|
+static inline void set_local_data_seg_from_sge(struct xsc_qp *qp, struct xsc_wqe_data_seg *data_seg,
|
|
+ const struct ibv_sge *sg)
|
|
{
|
|
- WR_LE_32(data_seg->seg_len, sg->length);
|
|
- WR_LE_32(data_seg->mkey, sg->lkey);
|
|
- WR_LE_64(data_seg->va, sg->addr);
|
|
+ struct xsc_context *ctx = to_xctx(qp->ibv_qp->context);
|
|
+
|
|
+ xsc_hw_set_data_seg(ctx->device_id, data_seg, sg->addr, sg->lkey, sg->length);
|
|
}
|
|
|
|
-static __be32 send_ieth(struct ibv_send_wr *wr)
|
|
+static void *get_addr_from_wr(const void *list, int idx)
|
|
{
|
|
- switch (wr->opcode) {
|
|
- case IBV_WR_SEND_WITH_IMM:
|
|
- case IBV_WR_RDMA_WRITE_WITH_IMM:
|
|
- return wr->imm_data;
|
|
- default:
|
|
- return 0;
|
|
- }
|
|
+ const struct ibv_send_wr *wr = list;
|
|
+
|
|
+ return (void *)wr->sg_list[idx].addr;
|
|
}
|
|
|
|
-static int set_data_inl_seg(struct xsc_qp *qp, struct ibv_send_wr *wr,
|
|
- struct xsc_send_wqe_ctrl_seg *ctrl)
|
|
+static int get_len_from_wr(const void *list, int idx)
|
|
{
|
|
- void *data_seg;
|
|
- unsigned seg_index;
|
|
- void *addr;
|
|
- int len = 0;
|
|
- int i;
|
|
- const int ds_len = sizeof(struct xsc_wqe_data_seg);
|
|
- int left_len = 0;
|
|
- int msg_len = ctrl->msg_len;
|
|
+ const struct ibv_send_wr *wr = list;
|
|
+ return wr->sg_list[idx].length;
|
|
+}
|
|
|
|
- if (wr->opcode == IBV_WR_SEND || wr->opcode == IBV_WR_SEND_WITH_IMM)
|
|
- seg_index = 1;
|
|
- else
|
|
- seg_index = 2;
|
|
+static void *get_addr_from_buf_list(const void *list, int idx)
|
|
+{
|
|
+ const struct ibv_data_buf *buf_list = list;
|
|
+ return buf_list[idx].addr;
|
|
+}
|
|
|
|
- if (unlikely(msg_len > qp->max_inline_data))
|
|
- return ENOMEM;
|
|
+static int get_len_from_wr_list(const void *list, int idx)
|
|
+{
|
|
+ const struct ibv_data_buf *buf_list = list;
|
|
+ return buf_list[idx].length;
|
|
+}
|
|
+
|
|
+static int _set_wqe_inline(void *data_seg, size_t num_buf, const void *list,
|
|
+ void *(*get_addr)(const void *, int),
|
|
+ int (*get_len)(const void *, int))
|
|
+{
|
|
+ int i;
|
|
+ int ds_left_len = 0;
|
|
+ int len = 0;
|
|
+ void *addr;
|
|
+ void *data_seg_base = data_seg;
|
|
+ int seg_index = 0;
|
|
+ const int ds_len = sizeof(struct xsc_wqe_data_seg);
|
|
|
|
- for (i = 0; i < wr->num_sge; ++i) {
|
|
- if (likely(wr->sg_list[i].length)) {
|
|
- addr = (void*)wr->sg_list[i].addr;
|
|
- len = wr->sg_list[i].length;
|
|
- if (left_len > 0) {
|
|
- int copy_len = min_t(int, len, left_len);
|
|
+ for (i = 0; i < num_buf; i++) {
|
|
+ addr = get_addr(list, i);
|
|
+ len = get_len(list, i);
|
|
+ if (likely(len)) {
|
|
+ if (ds_left_len > 0) {
|
|
+ int copy_len = min_t(int, len, ds_left_len);
|
|
memcpy(data_seg, addr, copy_len);
|
|
addr += copy_len;
|
|
len -= copy_len;
|
|
}
|
|
|
|
while (len >= ds_len) {
|
|
- data_seg = get_seg_wqe(ctrl, seg_index);
|
|
+ data_seg = get_seg_wqe(data_seg_base, seg_index);
|
|
seg_index++;
|
|
memcpy(data_seg, addr, ds_len);
|
|
addr += ds_len;
|
|
@@ -142,43 +144,84 @@ static int set_data_inl_seg(struct xsc_qp *qp, struct ibv_send_wr *wr,
|
|
}
|
|
|
|
if (len > 0) {
|
|
- data_seg = get_seg_wqe(ctrl, seg_index);
|
|
+ data_seg = get_seg_wqe(data_seg_base, seg_index);
|
|
seg_index++;
|
|
memcpy(data_seg, addr, len);
|
|
data_seg += len;
|
|
- left_len = ds_len - len;
|
|
+ ds_left_len = ds_len - len;
|
|
} else {
|
|
- left_len = 0;
|
|
+ ds_left_len = 0;
|
|
}
|
|
}
|
|
}
|
|
+ return seg_index;
|
|
+}
|
|
+
|
|
+static int set_wqe_inline_from_wr(struct xsc_qp *qp, struct ibv_send_wr *wr,
|
|
+ struct xsc_send_wqe_ctrl_seg *ctrl)
|
|
+{
|
|
+ void *data_seg;
|
|
+ unsigned seg_index;
|
|
+ int msg_len = ctrl->msg_len;
|
|
+ int filled_ds_num;
|
|
+
|
|
+ if (wr->opcode == IBV_WR_SEND || wr->opcode == IBV_WR_SEND_WITH_IMM)
|
|
+ seg_index = 1;
|
|
+ else
|
|
+ seg_index = 2;
|
|
+ data_seg = get_seg_wqe(ctrl, seg_index);
|
|
|
|
- ctrl->ds_data_num = seg_index - 1;
|
|
+ if (unlikely(msg_len > qp->max_inline_data))
|
|
+ return ENOMEM;
|
|
+
|
|
+ filled_ds_num = _set_wqe_inline(data_seg, wr->num_sge, wr,
|
|
+ get_addr_from_wr,
|
|
+ get_len_from_wr);
|
|
+ ctrl->ds_data_num = seg_index - 1 + filled_ds_num;
|
|
|
|
return 0;
|
|
}
|
|
|
|
-static void zero_send_ds(int idx, struct xsc_qp *qp)
|
|
+static int set_wqe_inline_from_buf_list(void *data_seg,
|
|
+ size_t num_buf,
|
|
+ const struct ibv_data_buf *buf_list)
|
|
+{
|
|
+ return _set_wqe_inline(data_seg, num_buf, buf_list,
|
|
+ get_addr_from_buf_list,
|
|
+ get_len_from_wr_list);
|
|
+}
|
|
+
|
|
+static inline void _zero_send_ds(int idx, struct xsc_qp *qp, int keep_ctrl)
|
|
{
|
|
void *seg;
|
|
uint64_t *uninitialized_var(p);
|
|
int i;
|
|
|
|
seg = (void*)xsc_get_send_wqe(qp, idx);
|
|
- for (i = 1; i < qp->sq.seg_cnt; i++) {
|
|
+ for (i = keep_ctrl; i < qp->sq.seg_cnt; i++) {
|
|
p = get_seg_wqe(seg, i);
|
|
p[0] = p[1] = 0;
|
|
}
|
|
}
|
|
|
|
-static void zero_recv_ds(int idx, struct xsc_qp *qp)
|
|
+static inline void clear_send_wqe(int idx, struct xsc_qp *qp)
|
|
+{
|
|
+ _zero_send_ds(idx, qp, 0);
|
|
+}
|
|
+
|
|
+static inline void clear_send_wqe_except_ctrl(int idx, struct xsc_qp *qp)
|
|
+{
|
|
+ _zero_send_ds(idx, qp, 1);
|
|
+}
|
|
+
|
|
+static void clear_recv_wqe(int idx, struct xsc_qp *qp)
|
|
{
|
|
void *seg;
|
|
uint64_t *uninitialized_var(p);
|
|
int i;
|
|
|
|
seg = (void*)get_recv_wqe(qp, idx);
|
|
- for (i = 1; i < qp->rq.seg_cnt; i++) {
|
|
+ for (i = 0; i < qp->rq.seg_cnt; i++) {
|
|
p = get_seg_wqe(seg, i);
|
|
p[0] = p[1] = 0;
|
|
}
|
|
@@ -221,23 +264,16 @@ static inline void dump_wqe(int type, int idx, struct xsc_qp *qp) {};
|
|
|
|
static inline void xsc_post_send_db(struct xsc_qp *qp, int nreq)
|
|
{
|
|
- uint16_t next_pid;
|
|
- union xsc_db_data db;
|
|
+ struct xsc_context *ctx = to_xctx(qp->ibv_qp->context);
|
|
+ uint32_t next_pid;
|
|
|
|
if (unlikely(!nreq))
|
|
return;
|
|
|
|
qp->sq.head += nreq;
|
|
next_pid = qp->sq.head << (qp->sq.wqe_shift - XSC_BASE_WQE_SHIFT);
|
|
- db.sq_next_pid = next_pid;
|
|
- db.sqn = qp->sqn;
|
|
- /*
|
|
- * Make sure that descriptors are written before
|
|
- * updating doorbell record and ringing the doorbell
|
|
- */
|
|
xsc_dbg(to_xctx(qp->ibv_qp->context)->dbg_fp, XSC_DBG_QP_SEND, "nreq:%d\n", nreq);
|
|
- udma_to_device_barrier();
|
|
- WR_REG(qp->sq.db, db.raw_data);
|
|
+ xsc_hw_ring_tx_doorbell(ctx->device_id, qp->sq.db, qp->sqn, next_pid);
|
|
}
|
|
|
|
static inline int _xsc_post_send(struct ibv_qp *ibqp, struct ibv_send_wr *wr,
|
|
@@ -305,7 +341,7 @@ static inline int _xsc_post_send(struct ibv_qp *ibqp, struct ibv_send_wr *wr,
|
|
}
|
|
|
|
idx = qp->sq.cur_post & (qp->sq.wqe_cnt - 1);
|
|
- zero_send_ds(idx, qp);
|
|
+ clear_send_wqe(idx, qp);
|
|
ctrl = seg = xsc_get_send_wqe(qp, idx);
|
|
ctrl->ds_data_num = 0;
|
|
WR_LE_16(ctrl->wqe_id,
|
|
@@ -337,11 +373,11 @@ static inline int _xsc_post_send(struct ibv_qp *ibqp, struct ibv_send_wr *wr,
|
|
break;
|
|
case IBV_WR_SEND_WITH_IMM:
|
|
ctrl->with_immdt = 1;
|
|
- ctrl->opcode_data = send_ieth(wr);
|
|
+ WR_LE_32(ctrl->opcode_data, RD_BE_32(wr->imm_data));
|
|
break;
|
|
case IBV_WR_RDMA_WRITE_WITH_IMM:
|
|
ctrl->with_immdt = 1;
|
|
- ctrl->opcode_data = send_ieth(wr);
|
|
+ WR_LE_32(ctrl->opcode_data, RD_BE_32(wr->imm_data));
|
|
SWITCH_FALLTHROUGH;
|
|
case IBV_WR_RDMA_READ:
|
|
case IBV_WR_RDMA_WRITE:
|
|
@@ -349,11 +385,11 @@ static inline int _xsc_post_send(struct ibv_qp *ibqp, struct ibv_send_wr *wr,
|
|
break;
|
|
ctrl->ds_data_num++;
|
|
data_seg = get_seg_wqe(ctrl, seg_index);
|
|
- set_remote_addr_seg(
|
|
- data_seg,
|
|
- msg_len,
|
|
- wr->wr.rdma.remote_addr,
|
|
- wr->wr.rdma.rkey);
|
|
+ set_data_seg_with_value(qp,
|
|
+ data_seg,
|
|
+ wr->wr.rdma.remote_addr,
|
|
+ wr->wr.rdma.rkey,
|
|
+ msg_len);
|
|
seg_index++;
|
|
break;
|
|
default:
|
|
@@ -372,7 +408,7 @@ static inline int _xsc_post_send(struct ibv_qp *ibqp, struct ibv_send_wr *wr,
|
|
}
|
|
|
|
if (wr->send_flags & IBV_SEND_INLINE && wr->num_sge) {
|
|
- err = set_data_inl_seg(qp, wr, ctrl);
|
|
+ err = set_wqe_inline_from_wr(qp, wr, ctrl);
|
|
if (unlikely(err)) {
|
|
*bad_wr = wr;
|
|
xsc_dbg(to_xctx(ibqp->context)->dbg_fp, XSC_DBG_QP_SEND,
|
|
@@ -383,7 +419,7 @@ static inline int _xsc_post_send(struct ibv_qp *ibqp, struct ibv_send_wr *wr,
|
|
for (i = 0; i < wr->num_sge; ++i, ++seg_index) {
|
|
if (likely(wr->sg_list[i].length)) {
|
|
data_seg = get_seg_wqe(ctrl, seg_index);
|
|
- set_local_data_seg(data_seg, &wr->sg_list[i]);
|
|
+ set_local_data_seg_from_sge(qp, data_seg, &wr->sg_list[i]);
|
|
ctrl->ds_data_num++;
|
|
}
|
|
}
|
|
@@ -392,7 +428,7 @@ static inline int _xsc_post_send(struct ibv_qp *ibqp, struct ibv_send_wr *wr,
|
|
ctrl->msg_opcode = xsc_ib_opcode[wr->opcode];
|
|
if (ctrl->msg_len == 0) {
|
|
ctrl->ds_data_num = 0;
|
|
- zero_send_ds(idx, qp);
|
|
+ clear_send_wqe_except_ctrl(idx, qp);
|
|
}
|
|
qp->sq.wrid[idx] = wr->wr_id;
|
|
qp->sq.wqe_head[idx] = qp->sq.head + nreq;
|
|
@@ -403,7 +439,7 @@ static inline int _xsc_post_send(struct ibv_qp *ibqp, struct ibv_send_wr *wr,
|
|
}
|
|
qp->sq.wr_opcode[idx] = wr->opcode;
|
|
|
|
- if (xsc_debug_mask & XSC_DBG_QP_SEND)
|
|
+ if (unlikely(xsc_debug_mask & XSC_DBG_QP_SEND))
|
|
dump_wqe(0, idx, qp);
|
|
}
|
|
|
|
@@ -420,6 +456,301 @@ int xsc_post_send(struct ibv_qp *ibqp, struct ibv_send_wr *wr,
|
|
return _xsc_post_send(ibqp, wr, bad_wr);
|
|
}
|
|
|
|
+static inline void xsc_wr_start(struct ibv_qp_ex *ibqp)
|
|
+{
|
|
+ struct xsc_qp *qp = to_xqp((struct ibv_qp *)ibqp);
|
|
+
|
|
+ xsc_spin_lock(&qp->sq.lock);
|
|
+
|
|
+ qp->cur_post_rb = qp->sq.cur_post;
|
|
+ qp->err = 0;
|
|
+ qp->nreq = 0;
|
|
+}
|
|
+
|
|
+static inline int xsc_wr_complete(struct ibv_qp_ex *ibqp)
|
|
+{
|
|
+ struct xsc_qp *qp = to_xqp((struct ibv_qp *)ibqp);
|
|
+ int err = qp->err;
|
|
+
|
|
+ if (unlikely(err)) {
|
|
+ qp->sq.cur_post = qp->cur_post_rb;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ xsc_post_send_db(qp, qp->nreq);
|
|
+out:
|
|
+ xsc_spin_unlock(&qp->sq.lock);
|
|
+ return err;
|
|
+}
|
|
+
|
|
+static inline void xsc_wr_abort(struct ibv_qp_ex *ibqp)
|
|
+{
|
|
+ struct xsc_qp *qp = to_xqp((struct ibv_qp *)ibqp);
|
|
+
|
|
+ qp->sq.cur_post = qp->cur_post_rb;
|
|
+
|
|
+ xsc_spin_unlock(&qp->sq.lock);
|
|
+}
|
|
+
|
|
+#define RDMA_REMOTE_DATA_SEG_IDX 1
|
|
+static const int local_ds_base_idx[] = {
|
|
+ [IBV_WR_RDMA_WRITE] = 2,
|
|
+ [IBV_WR_RDMA_WRITE_WITH_IMM] = 2,
|
|
+ [IBV_WR_SEND] = 1,
|
|
+ [IBV_WR_SEND_WITH_IMM] = 1,
|
|
+ [IBV_WR_RDMA_READ] = 2
|
|
+};
|
|
+
|
|
+static inline void _common_wqe_init(struct ibv_qp_ex *ibqp,
|
|
+ enum ibv_wr_opcode ib_op)
|
|
+{
|
|
+ struct xsc_qp *qp = to_xqp((struct ibv_qp *)ibqp);
|
|
+ struct xsc_send_wqe_ctrl_seg *ctrl;
|
|
+ uint32_t idx;
|
|
+
|
|
+ if (unlikely(xsc_wq_overflow(&qp->sq, qp->nreq,
|
|
+ to_xcq(qp->ibv_qp->send_cq)))) {
|
|
+ xsc_dbg(to_xctx(ibqp->qp_base.context)->dbg_fp, XSC_DBG_QP_SEND,
|
|
+ "send work queue overflow\n");
|
|
+ if (!qp->err)
|
|
+ qp->err = ENOMEM;
|
|
+
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ idx = qp->sq.cur_post & (qp->sq.wqe_cnt - 1);
|
|
+ clear_send_wqe(idx, qp);
|
|
+ ctrl = xsc_get_send_wqe(qp, idx);
|
|
+ qp->cur_ctrl = ctrl;
|
|
+ qp->cur_ds_num = 0;
|
|
+ qp->cur_data_len = 0;
|
|
+ qp->cur_data = get_seg_wqe(ctrl, local_ds_base_idx[ib_op]);
|
|
+ qp->cur_remote_addr = 0;
|
|
+ qp->cur_remote_key = 0;
|
|
+ ctrl->msg_opcode = xsc_ib_opcode[ib_op];
|
|
+ ctrl->ce = qp->sq_signal_bits ? 1 : (ibqp->wr_flags & IBV_SEND_SIGNALED ? 1 : 0);
|
|
+ ctrl->se = ibqp->wr_flags & IBV_SEND_SOLICITED ? 1 : 0;
|
|
+ ctrl->in_line = ibqp->wr_flags & IBV_SEND_INLINE ? 1 : 0;
|
|
+ qp->sq.wrid[idx] = ibqp->wr_id;
|
|
+ qp->sq.wqe_head[idx] = qp->sq.head + qp->nreq;
|
|
+ qp->sq.wr_opcode[idx] = ib_op;
|
|
+ WR_LE_16(ctrl->wqe_id,
|
|
+ qp->sq.cur_post << (qp->sq.wqe_shift - XSC_BASE_WQE_SHIFT));
|
|
+}
|
|
+
|
|
+static inline void _common_wqe_finilize(struct ibv_qp_ex *ibqp)
|
|
+{
|
|
+ struct xsc_qp *qp = to_xqp((struct ibv_qp *)ibqp);
|
|
+ struct xsc_send_wqe_ctrl_seg *ctrl = qp->cur_ctrl;
|
|
+ struct xsc_wqe_data_seg *remote_seg;
|
|
+ uint32_t idx = qp->sq.cur_post & (qp->sq.wqe_cnt - 1);
|
|
+
|
|
+ ctrl->ds_data_num = qp->cur_ds_num;
|
|
+ ctrl->msg_len = qp->cur_data_len;
|
|
+ if (ctrl->msg_opcode == XSC_MSG_OPCODE_RDMA_WRITE ||
|
|
+ ctrl->msg_opcode == XSC_MSG_OPCODE_RDMA_READ) {
|
|
+ remote_seg = get_seg_wqe(qp->cur_ctrl, RDMA_REMOTE_DATA_SEG_IDX);
|
|
+ set_data_seg_with_value(qp, remote_seg,
|
|
+ qp->cur_remote_addr,
|
|
+ qp->cur_remote_key,
|
|
+ ctrl->msg_len);
|
|
+ }
|
|
+
|
|
+ dump_wqe(0, idx, qp);
|
|
+ qp->sq.cur_post++;
|
|
+ qp->nreq++;
|
|
+ if (ctrl->ce) {
|
|
+ qp->sq.flush_wqe_cnt++;
|
|
+ qp->sq.need_flush[idx] = 1;
|
|
+ }
|
|
+}
|
|
+
|
|
+static inline void xsc_wr_send(struct ibv_qp_ex *ibqp)
|
|
+{
|
|
+ _common_wqe_init(ibqp, IBV_WR_SEND);
|
|
+}
|
|
+
|
|
+static inline void xsc_wr_send_imm(struct ibv_qp_ex *ibqp, __be32 imm_data)
|
|
+{
|
|
+ struct xsc_qp *qp = to_xqp((struct ibv_qp *)ibqp);
|
|
+ struct xsc_send_wqe_ctrl_seg *ctrl;
|
|
+
|
|
+ _common_wqe_init(ibqp, IBV_WR_SEND_WITH_IMM);
|
|
+ ctrl = qp->cur_ctrl;
|
|
+ ctrl->with_immdt = 1;
|
|
+ WR_LE_32(ctrl->opcode_data, RD_BE_32(imm_data));
|
|
+}
|
|
+
|
|
+static inline void _xsc_wr_rdma(struct ibv_qp_ex *ibqp,
|
|
+ uint32_t rkey,
|
|
+ uint64_t remote_addr,
|
|
+ enum ibv_wr_opcode ib_op)
|
|
+{
|
|
+ struct xsc_qp *qp = to_xqp((struct ibv_qp *)ibqp);
|
|
+
|
|
+ _common_wqe_init(ibqp, ib_op);
|
|
+ qp->cur_remote_addr = remote_addr;
|
|
+ qp->cur_remote_key = rkey;
|
|
+ qp->cur_ds_num++;
|
|
+}
|
|
+
|
|
+static inline void xsc_wr_rdma_write(struct ibv_qp_ex *ibqp, uint32_t rkey,
|
|
+ uint64_t remote_addr)
|
|
+{
|
|
+ _xsc_wr_rdma(ibqp, rkey, remote_addr, IBV_WR_RDMA_WRITE);
|
|
+}
|
|
+
|
|
+static inline void xsc_wr_rdma_write_imm(struct ibv_qp_ex *ibqp, uint32_t rkey,
|
|
+ uint64_t remote_addr, __be32 imm_data)
|
|
+{
|
|
+ struct xsc_qp *qp = to_xqp((struct ibv_qp *)ibqp);
|
|
+ struct xsc_send_wqe_ctrl_seg *ctrl;
|
|
+
|
|
+ _xsc_wr_rdma(ibqp, rkey, remote_addr, IBV_WR_RDMA_WRITE_WITH_IMM);
|
|
+ ctrl = qp->cur_ctrl;
|
|
+ ctrl->with_immdt = 1;
|
|
+ WR_LE_32(ctrl->opcode_data, RD_BE_32(imm_data));
|
|
+}
|
|
+
|
|
+static inline void xsc_wr_rdma_read(struct ibv_qp_ex *ibqp, uint32_t rkey,
|
|
+ uint64_t remote_addr)
|
|
+{
|
|
+ _xsc_wr_rdma(ibqp, rkey, remote_addr, IBV_WR_RDMA_READ);
|
|
+}
|
|
+
|
|
+static inline void xsc_wr_set_sge(struct ibv_qp_ex *ibqp, uint32_t lkey, uint64_t addr,
|
|
+ uint32_t length)
|
|
+{
|
|
+ struct xsc_qp *qp = to_xqp((struct ibv_qp *)ibqp);
|
|
+ struct xsc_wqe_data_seg *data_seg = qp->cur_data;
|
|
+
|
|
+ if (unlikely(!length))
|
|
+ return;
|
|
+
|
|
+ set_data_seg_with_value(qp, data_seg, addr, lkey, length);
|
|
+ qp->cur_ds_num++;
|
|
+ qp->cur_data_len = length;
|
|
+ _common_wqe_finilize(ibqp);
|
|
+}
|
|
+
|
|
+static inline void xsc_wr_set_sge_list(struct ibv_qp_ex *ibqp, size_t num_sge,
|
|
+ const struct ibv_sge *sg_list)
|
|
+{
|
|
+ struct xsc_qp *qp = to_xqp((struct ibv_qp *)ibqp);
|
|
+ struct xsc_wqe_data_seg *data_seg = qp->cur_data;
|
|
+ int i;
|
|
+
|
|
+ if (unlikely(num_sge > qp->sq.max_gs)) {
|
|
+ xsc_dbg(to_xctx(ibqp->qp_base.context)->dbg_fp, XSC_DBG_QP_SEND,
|
|
+ "rdma read, max gs exceeded %lu (max = 1)\n",
|
|
+ num_sge);
|
|
+ if (!qp->err)
|
|
+ qp->err = ENOMEM;
|
|
+ return ;
|
|
+ }
|
|
+
|
|
+ for (i = 0; i < num_sge; i++) {
|
|
+ if (unlikely(!sg_list[i].length))
|
|
+ continue;
|
|
+ set_local_data_seg_from_sge(qp, data_seg, &sg_list[i]);
|
|
+ data_seg++;
|
|
+ qp->cur_ds_num++;
|
|
+ qp->cur_data_len += sg_list[i].length;
|
|
+ }
|
|
+ _common_wqe_finilize(ibqp);
|
|
+}
|
|
+
|
|
+static inline void xsc_wr_set_inline_data(struct ibv_qp_ex *ibqp, void *addr,
|
|
+ size_t length)
|
|
+{
|
|
+ struct xsc_qp *qp = to_xqp((struct ibv_qp *)ibqp);
|
|
+ struct xsc_wqe_data_seg *data_seg = qp->cur_data;
|
|
+ size_t num_buf = 1;
|
|
+ struct ibv_data_buf data_buf = {.addr = addr, .length = length};
|
|
+ int num_filled_ds = 0;
|
|
+
|
|
+ if (unlikely(length > qp->max_inline_data)) {
|
|
+ if (!qp->err)
|
|
+ qp->err = ENOMEM;
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ num_filled_ds = set_wqe_inline_from_buf_list(data_seg, num_buf, &data_buf);
|
|
+
|
|
+ qp->cur_ds_num += num_filled_ds;
|
|
+ qp->cur_data_len = length;
|
|
+ _common_wqe_finilize(ibqp);
|
|
+}
|
|
+
|
|
+static inline void xsc_wr_set_inline_data_list(struct ibv_qp_ex *ibqp,
|
|
+ size_t num_buf,
|
|
+ const struct ibv_data_buf *buf_list)
|
|
+{
|
|
+ struct xsc_qp *qp = to_xqp((struct ibv_qp *)ibqp);
|
|
+ struct xsc_wqe_data_seg *data_seg = qp->cur_data;
|
|
+ int num_filled_ds = 0;
|
|
+ int i;
|
|
+ size_t total_len = 0;
|
|
+
|
|
+ for (i = 0; i < num_buf; i++)
|
|
+ total_len += buf_list[i].length;
|
|
+ if (unlikely(total_len > qp->max_inline_data)) {
|
|
+ if (!qp->err)
|
|
+ qp->err = ENOMEM;
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ num_filled_ds = set_wqe_inline_from_buf_list(data_seg, num_buf, buf_list);
|
|
+
|
|
+ qp->cur_ds_num += num_filled_ds;
|
|
+ qp->cur_data_len = total_len;
|
|
+ _common_wqe_finilize(ibqp);
|
|
+}
|
|
+
|
|
+enum {
|
|
+ XSC_SUPPORTED_SEND_OPS_FLAGS_RC =
|
|
+ IBV_QP_EX_WITH_SEND |
|
|
+ IBV_QP_EX_WITH_SEND_WITH_IMM |
|
|
+ IBV_QP_EX_WITH_RDMA_WRITE |
|
|
+ IBV_QP_EX_WITH_RDMA_WRITE_WITH_IMM |
|
|
+ IBV_QP_EX_WITH_RDMA_READ,
|
|
+};
|
|
+
|
|
+static void fill_wr_pfns_rc(struct ibv_qp_ex *ibqp)
|
|
+{
|
|
+ ibqp->wr_send = xsc_wr_send;
|
|
+ ibqp->wr_send_imm = xsc_wr_send_imm;
|
|
+ ibqp->wr_rdma_write = xsc_wr_rdma_write;
|
|
+ ibqp->wr_rdma_write_imm = xsc_wr_rdma_write_imm;
|
|
+ ibqp->wr_rdma_read = xsc_wr_rdma_read;
|
|
+
|
|
+ ibqp->wr_set_sge = xsc_wr_set_sge;
|
|
+ ibqp->wr_set_sge_list = xsc_wr_set_sge_list;
|
|
+ ibqp->wr_set_inline_data = xsc_wr_set_inline_data;
|
|
+ ibqp->wr_set_inline_data_list = xsc_wr_set_inline_data_list;
|
|
+}
|
|
+
|
|
+int xsc_qp_fill_wr_pfns(struct xsc_qp *xqp, const struct ibv_qp_init_attr_ex *attr)
|
|
+{
|
|
+ struct ibv_qp_ex *ibqp = &xqp->verbs_qp.qp_ex;
|
|
+ uint64_t ops = attr->send_ops_flags;
|
|
+
|
|
+ ibqp->wr_start = xsc_wr_start;
|
|
+ ibqp->wr_complete = xsc_wr_complete;
|
|
+ ibqp->wr_abort = xsc_wr_abort;
|
|
+
|
|
+ switch (attr->qp_type) {
|
|
+ case IBV_QPT_RC:
|
|
+ if (ops & ~XSC_SUPPORTED_SEND_OPS_FLAGS_RC)
|
|
+ return EOPNOTSUPP;
|
|
+ fill_wr_pfns_rc(ibqp);
|
|
+ break;
|
|
+ default:
|
|
+ return EOPNOTSUPP;
|
|
+ }
|
|
+ return 0;
|
|
+}
|
|
+
|
|
static void set_wq_sig_seg(struct xsc_rwq *rwq, struct xsc_rwqe_sig *sig,
|
|
int size, uint16_t idx)
|
|
{
|
|
@@ -506,6 +837,7 @@ out:
|
|
return err;
|
|
}
|
|
|
|
+int xsc_post_recv_dump_wqe = 1;
|
|
int xsc_post_recv(struct ibv_qp *ibqp, struct ibv_recv_wr *wr,
|
|
struct ibv_recv_wr **bad_wr)
|
|
{
|
|
@@ -513,8 +845,7 @@ int xsc_post_recv(struct ibv_qp *ibqp, struct ibv_recv_wr *wr,
|
|
struct xsc_wqe_data_seg *recv_head;
|
|
struct xsc_wqe_data_seg *data_seg;
|
|
int err = 0;
|
|
- uint16_t next_pid = 0;
|
|
- union xsc_db_data db;
|
|
+ uint32_t next_pid = 0;
|
|
int nreq;
|
|
uint16_t idx;
|
|
int i;
|
|
@@ -523,7 +854,7 @@ int xsc_post_recv(struct ibv_qp *ibqp, struct ibv_recv_wr *wr,
|
|
|
|
idx = qp->rq.head & (qp->rq.wqe_cnt - 1);
|
|
|
|
- zero_recv_ds(idx, qp);
|
|
+ clear_recv_wqe(idx, qp);
|
|
for (nreq = 0; wr; ++nreq, wr = wr->next) {
|
|
if (unlikely(xsc_wq_overflow(&qp->rq, nreq,
|
|
to_xcq(qp->ibv_qp->recv_cq)))) {
|
|
@@ -547,31 +878,23 @@ int xsc_post_recv(struct ibv_qp *ibqp, struct ibv_recv_wr *wr,
|
|
if (unlikely(!wr->sg_list[i].length))
|
|
continue;
|
|
data_seg = get_seg_wqe(recv_head, i);
|
|
- WR_LE_32(data_seg->seg_len, wr->sg_list[i].length);
|
|
- WR_LE_32(data_seg->mkey, wr->sg_list[i].lkey);
|
|
- WR_LE_64(data_seg->va, wr->sg_list[i].addr);
|
|
+ set_local_data_seg_from_sge(qp, data_seg, &wr->sg_list[i]);
|
|
}
|
|
|
|
qp->rq.wrid[idx] = wr->wr_id;
|
|
|
|
- dump_wqe(1, idx, qp);
|
|
+ if (xsc_post_recv_dump_wqe || (xsc_debug_mask & XSC_DBG_QP_RECV))
|
|
+ dump_wqe(1, idx, qp);
|
|
idx = (idx + 1) & (qp->rq.wqe_cnt - 1);
|
|
qp->rq.flush_wqe_cnt++;
|
|
}
|
|
|
|
out:
|
|
if (likely(nreq)) {
|
|
+ struct xsc_context *ctx = to_xctx(ibqp->context);
|
|
qp->rq.head += nreq;
|
|
next_pid = qp->rq.head << (qp->rq.wqe_shift - XSC_BASE_WQE_SHIFT);
|
|
- db.rq_next_pid = next_pid;
|
|
- db.rqn = qp->rqn;
|
|
-
|
|
- /*
|
|
- * Make sure that descriptors are written before
|
|
- * doorbell record.
|
|
- */
|
|
- udma_to_device_barrier();
|
|
- WR_REG(qp->rq.db, db.raw_data);
|
|
+ xsc_hw_ring_rx_doorbell(ctx->device_id, qp->rq.db, qp->rqn, next_pid);
|
|
}
|
|
|
|
xsc_spin_unlock(&qp->rq.lock);
|
|
@@ -676,3 +999,4 @@ int xsc_err_state_qp(struct ibv_qp *qp, enum ibv_qp_state cur_state,
|
|
}
|
|
return ret;
|
|
}
|
|
+
|
|
diff --git a/providers/xscale/verbs.c b/providers/xscale/verbs.c
|
|
index 937bed1..602ca9d 100644
|
|
--- a/providers/xscale/verbs.c
|
|
+++ b/providers/xscale/verbs.c
|
|
@@ -213,7 +213,6 @@ struct ibv_mr *xsc_reg_mr(struct ibv_pd *pd, void *addr, size_t length,
|
|
&mr->vmr, &cmd, sizeof(cmd), &resp,
|
|
sizeof resp);
|
|
if (ret) {
|
|
- xsc_free_buf(&(mr->buf));
|
|
free(mr);
|
|
return NULL;
|
|
}
|
|
@@ -225,6 +224,27 @@ struct ibv_mr *xsc_reg_mr(struct ibv_pd *pd, void *addr, size_t length,
|
|
return &mr->vmr.ibv_mr;
|
|
}
|
|
|
|
+struct ibv_mr *xsc_reg_dmabuf_mr(struct ibv_pd *pd, uint64_t offset, size_t length,
|
|
+ uint64_t iova, int fd, int acc)
|
|
+{
|
|
+ struct xsc_mr *mr;
|
|
+ int ret;
|
|
+
|
|
+ mr = calloc(1, sizeof(*mr));
|
|
+ if (!mr)
|
|
+ return NULL;
|
|
+
|
|
+ ret = ibv_cmd_reg_dmabuf_mr(pd, offset, length, iova, fd, acc,
|
|
+ &mr->vmr);
|
|
+ if (ret) {
|
|
+ free(mr);
|
|
+ return NULL;
|
|
+ }
|
|
+ mr->alloc_flags = acc;
|
|
+
|
|
+ return &mr->vmr.ibv_mr;
|
|
+}
|
|
+
|
|
struct ibv_mr *xsc_alloc_null_mr(struct ibv_pd *pd)
|
|
{
|
|
struct xsc_mr *mr;
|
|
@@ -291,17 +311,6 @@ struct ibv_mr *xsc_reg_dm_mr(struct ibv_pd *pd, struct ibv_dm *ibdm,
|
|
return &mr->vmr.ibv_mr;
|
|
}
|
|
|
|
-int xsc_rereg_mr(struct verbs_mr *vmr, int flags, struct ibv_pd *pd,
|
|
- void *addr, size_t length, int access)
|
|
-{
|
|
- struct ibv_rereg_mr cmd;
|
|
- struct ib_uverbs_rereg_mr_resp resp;
|
|
-
|
|
- return ibv_cmd_rereg_mr(vmr, flags, addr, length, (uintptr_t)addr,
|
|
- access, pd, &cmd, sizeof(cmd), &resp,
|
|
- sizeof(resp));
|
|
-}
|
|
-
|
|
int xsc_dereg_mr(struct verbs_mr *vmr)
|
|
{
|
|
int ret;
|
|
@@ -339,12 +348,8 @@ static int align_queue_size(long long req)
|
|
}
|
|
|
|
enum {
|
|
- CREATE_CQ_SUPPORTED_WC_FLAGS = IBV_WC_STANDARD_FLAGS |
|
|
- IBV_WC_EX_WITH_COMPLETION_TIMESTAMP |
|
|
- IBV_WC_EX_WITH_CVLAN |
|
|
- IBV_WC_EX_WITH_FLOW_TAG |
|
|
- IBV_WC_EX_WITH_TM_INFO |
|
|
- IBV_WC_EX_WITH_COMPLETION_TIMESTAMP_WALLCLOCK
|
|
+ CREATE_CQ_SUPPORTED_WC_FLAGS = IBV_WC_STANDARD_FLAGS |
|
|
+ IBV_WC_EX_WITH_COMPLETION_TIMESTAMP
|
|
};
|
|
|
|
enum {
|
|
@@ -417,7 +422,7 @@ static struct ibv_cq_ex *create_cq(struct ibv_context *context,
|
|
}
|
|
|
|
if (cq_attr->wc_flags & ~CREATE_CQ_SUPPORTED_WC_FLAGS) {
|
|
- xsc_err("unsupported flgas:0x%lx\n", cq_attr->wc_flags);
|
|
+ xsc_err("unsupported wc flags:0x%lx\n", cq_attr->wc_flags);
|
|
errno = ENOTSUP;
|
|
return NULL;
|
|
}
|
|
@@ -453,16 +458,16 @@ static struct ibv_cq_ex *create_cq(struct ibv_context *context,
|
|
ncqe = XSC_CQE_RING_DEPTH_MIN;
|
|
}
|
|
|
|
- if (ncqe > XSC_CQE_RING_DEPTH_MAX) {
|
|
+ if (ncqe > xctx->max_cqe) {
|
|
if (xsc_cqe_depth_check()) {
|
|
xsc_err("CQE ring size %u exceeds CQE ring depth %u, abort!\n",
|
|
- ncqe, XSC_CQE_RING_DEPTH_MAX);
|
|
+ ncqe, xctx->max_cqe);
|
|
errno = EINVAL;
|
|
goto err_spl;
|
|
} else {
|
|
xsc_dbg(xctx->dbg_fp, XSC_DBG_CQ, "CQE ring size %u exceeds the MAX ring szie, set it as %u\n",
|
|
- ncqe, XSC_CQE_RING_DEPTH_MAX);
|
|
- ncqe = XSC_CQE_RING_DEPTH_MAX;
|
|
+ ncqe, xctx->max_cqe);
|
|
+ ncqe = xctx->max_cqe;
|
|
}
|
|
}
|
|
|
|
@@ -485,6 +490,9 @@ static struct ibv_cq_ex *create_cq(struct ibv_context *context,
|
|
|
|
xsc_dbg(xctx->dbg_fp, XSC_DBG_CQ, "buf_addr:%p\n", cq->buf_a.buf);
|
|
|
|
+ if (cq_alloc_flags & XSC_CQ_FLAGS_EXTENDED)
|
|
+ xsc_cq_fill_pfns(cq, cq_attr);
|
|
+
|
|
if (use_ex) {
|
|
struct ibv_cq_init_attr_ex cq_attr_ex = *cq_attr;
|
|
|
|
@@ -630,6 +638,7 @@ static int xsc_calc_sq_size(struct xsc_context *ctx,
|
|
int wqe_size;
|
|
int wq_size;
|
|
int wq_size_min = 0;
|
|
+ int max_inline_cap;
|
|
|
|
if (!attr->cap.max_send_wr)
|
|
return 0;
|
|
@@ -646,23 +655,34 @@ static int xsc_calc_sq_size(struct xsc_context *ctx,
|
|
wq_size = wq_size_min;
|
|
}
|
|
|
|
- if (wq_size > XSC_SEND_WQE_RING_DEPTH_MAX) {
|
|
- xsc_dbg(ctx->dbg_fp, XSC_DBG_QP,
|
|
- "WQE size %u exceeds WQE ring depth, set it as %u\n",
|
|
- wq_size, XSC_SEND_WQE_RING_DEPTH_MAX);
|
|
- wq_size = XSC_SEND_WQE_RING_DEPTH_MAX;
|
|
+ if (wq_size > ctx->max_send_wqebb) {
|
|
+ if (ctx->device_id == XSC_MC_PF_DEV_ID_DIAMOND ||
|
|
+ ctx->device_id == XSC_MC_PF_DEV_ID_DIAMOND_NEXT) {
|
|
+ xsc_err("WQE size %u exceeds WQE ring depth\n", wq_size);
|
|
+ return -EINVAL;
|
|
+ } else {
|
|
+ xsc_dbg(ctx->dbg_fp, XSC_DBG_QP,
|
|
+ "WQE size %u exceeds WQE ring depth, set it as %u\n",
|
|
+ wq_size, ctx->max_send_wqebb);
|
|
+ wq_size = ctx->max_send_wqebb;
|
|
+ }
|
|
}
|
|
|
|
- qp->max_inline_data = attr->cap.max_inline_data;
|
|
qp->sq.wqe_cnt = wq_size;
|
|
qp->sq.ds_cnt = wq_size << ctx->send_ds_shift;
|
|
qp->sq.seg_cnt = 1 << ctx->send_ds_shift;
|
|
qp->sq.wqe_shift = XSC_BASE_WQE_SHIFT + ctx->send_ds_shift;
|
|
qp->sq.max_gs = attr->cap.max_send_sge;
|
|
qp->sq.max_post = qp->sq.wqe_cnt;
|
|
- if (attr->cap.max_inline_data >
|
|
- (qp->sq.seg_cnt - 2) * sizeof(struct xsc_wqe_data_seg))
|
|
+
|
|
+ if (ctx->device_id == XSC_MC_PF_DEV_ID_DIAMOND ||
|
|
+ ctx->device_id == XSC_MC_PF_DEV_ID_DIAMOND_NEXT)
|
|
+ max_inline_cap = 64;
|
|
+ else
|
|
+ max_inline_cap = (qp->sq.seg_cnt - 2) * sizeof(struct xsc_wqe_data_seg);
|
|
+ if (attr->cap.max_inline_data > max_inline_cap)
|
|
return -EINVAL;
|
|
+ qp->max_inline_data = attr->cap.max_inline_data;
|
|
|
|
xsc_dbg(ctx->dbg_fp, XSC_DBG_QP, "Send WQE count:%u, max post:%u wqe shift:%u\n",
|
|
qp->sq.wqe_cnt, qp->sq.max_post, qp->sq.wqe_shift);
|
|
@@ -743,11 +763,17 @@ static int xsc_calc_rq_size(struct xsc_context *ctx,
|
|
wq_size = wq_size_min;
|
|
}
|
|
|
|
- if (wq_size > XSC_RECV_WQE_RING_DEPTH_MAX) {
|
|
- xsc_dbg(ctx->dbg_fp, XSC_DBG_QP,
|
|
- "WQE size %u exceeds WQE ring depth, set it as %u\n",
|
|
- wq_size, XSC_RECV_WQE_RING_DEPTH_MAX);
|
|
- wq_size = XSC_RECV_WQE_RING_DEPTH_MAX;
|
|
+ if (wq_size > ctx->max_recv_wr) {
|
|
+ if (ctx->device_id == XSC_MC_PF_DEV_ID_DIAMOND ||
|
|
+ ctx->device_id == XSC_MC_PF_DEV_ID_DIAMOND_NEXT) {
|
|
+ xsc_err("WQE size %u exceeds WQE ring depth\n", wq_size);
|
|
+ return -EINVAL;
|
|
+ } else {
|
|
+ xsc_dbg(ctx->dbg_fp, XSC_DBG_QP,
|
|
+ "WQE size %u exceeds WQE ring depth, set it as %u\n",
|
|
+ wq_size, ctx->max_recv_wr);
|
|
+ wq_size = ctx->max_recv_wr;
|
|
+ }
|
|
}
|
|
|
|
qp->rq.wqe_cnt = wq_size;
|
|
@@ -946,8 +972,10 @@ static void xsc_free_qp_buf(struct xsc_context *ctx, struct xsc_qp *qp)
|
|
}
|
|
|
|
enum {
|
|
- XSC_CREATE_QP_SUP_COMP_MASK = IBV_QP_INIT_ATTR_PD |
|
|
- IBV_QP_INIT_ATTR_CREATE_FLAGS
|
|
+ XSC_CREATE_QP_SUP_COMP_MASK = (IBV_QP_INIT_ATTR_PD |
|
|
+ IBV_QP_INIT_ATTR_CREATE_FLAGS |
|
|
+ IBV_QP_INIT_ATTR_SEND_OPS_FLAGS |
|
|
+ IBV_QP_INIT_ATTR_MAX_TSO_HEADER),
|
|
};
|
|
|
|
enum {
|
|
@@ -971,6 +999,34 @@ enum {
|
|
XSCDV_QP_CREATE_ALLOW_SCATTER_TO_CQE),
|
|
};
|
|
|
|
+static int xsc_cmd_create_qp_ex(struct ibv_context *context,
|
|
+ struct ibv_qp_init_attr_ex *attr,
|
|
+ struct xsc_create_qp *cmd,
|
|
+ struct xsc_qp *qp,
|
|
+ struct xsc_create_qp_resp *resp,
|
|
+ struct xsc_create_qp_ex_resp *resp_ex)
|
|
+{
|
|
+ struct xsc_create_qp_ex cmd_ex;
|
|
+ int ret;
|
|
+
|
|
+ if (attr->comp_mask & XSC_CREATE_QP_EX2_COMP_MASK) {
|
|
+ memset(&cmd_ex, 0, sizeof(cmd_ex));
|
|
+ *ibv_create_qp_ex_to_reg(&cmd_ex.ibv_cmd) = cmd->ibv_cmd.core_payload;
|
|
+ cmd_ex.drv_payload = cmd->drv_payload;
|
|
+
|
|
+ ret = ibv_cmd_create_qp_ex2(context, &qp->verbs_qp,
|
|
+ attr, &cmd_ex.ibv_cmd,
|
|
+ sizeof(cmd_ex), &resp_ex->ibv_resp,
|
|
+ sizeof(*resp_ex));
|
|
+ } else {
|
|
+ ret = ibv_cmd_create_qp_ex(context, &qp->verbs_qp, attr,
|
|
+ &cmd->ibv_cmd, sizeof(*cmd),
|
|
+ &resp->ibv_resp, sizeof(*resp));
|
|
+ }
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
static struct ibv_qp *create_qp(struct ibv_context *context,
|
|
struct ibv_qp_init_attr_ex *attr,
|
|
struct xscdv_qp_init_attr *xqp_attr)
|
|
@@ -992,19 +1048,35 @@ static struct ibv_qp *create_qp(struct ibv_context *context,
|
|
return NULL;
|
|
}
|
|
|
|
+ /*check qp_type*/
|
|
+ if ((attr->qp_type != IBV_QPT_RC) &&
|
|
+ (attr->qp_type != IBV_QPT_RAW_PACKET)){
|
|
+ xsc_err("Not supported qp_type:0x%x\n", attr->qp_type);
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
qp = calloc(1, sizeof(*qp));
|
|
if (!qp) {
|
|
xsc_err("QP calloc failed\n");
|
|
return NULL;
|
|
}
|
|
|
|
- ibqp = (struct ibv_qp *)&qp->verbs_qp;
|
|
+ ibqp = &qp->verbs_qp.qp;
|
|
qp->ibv_qp = ibqp;
|
|
|
|
memset(&cmd, 0, sizeof(cmd));
|
|
memset(&resp, 0, sizeof(resp));
|
|
memset(&resp_ex, 0, sizeof(resp_ex));
|
|
|
|
+ if (attr->comp_mask & IBV_QP_INIT_ATTR_SEND_OPS_FLAGS) {
|
|
+ ret = xsc_qp_fill_wr_pfns(qp, attr);
|
|
+ if (ret) {
|
|
+ errno = ret;
|
|
+ xsc_err("Fill wr pfns failed\n");
|
|
+ goto err;
|
|
+ }
|
|
+ }
|
|
+
|
|
ret = xsc_calc_wq_size(ctx, attr, qp);
|
|
if (ret < 0) {
|
|
xsc_err("Calculate WQ size failed\n");
|
|
@@ -1056,17 +1128,28 @@ static struct ibv_qp *create_qp(struct ibv_context *context,
|
|
"revert create_flags(0x%x) to cmd_flags(0x%x)\n",
|
|
attr->create_flags, cmd.flags);
|
|
}
|
|
+
|
|
+ if (attr->create_flags & XSC_QP_CREATE_RAWPACKET_SNIFFER) {
|
|
+ cmd.flags |= XSC_QP_FLAG_RAWPACKET_SNIFFER;
|
|
+ qp->flags |= XSC_QP_FLAG_RAWPACKET_SNIFFER;
|
|
+ xsc_dbg(ctx->dbg_fp, XSC_DBG_QP,
|
|
+ "revert create_flags(0x%x) to cmd_flags(0x%x)\n",
|
|
+ attr->create_flags, cmd.flags);
|
|
+ }
|
|
+
|
|
attr->comp_mask &= ~IBV_QP_INIT_ATTR_CREATE_FLAGS;
|
|
}
|
|
+
|
|
+ if (attr->comp_mask & IBV_QP_INIT_ATTR_MAX_TSO_HEADER)
|
|
+ cmd.flags |= XSC_QP_FLAG_RAWPACKET_TSO;
|
|
+
|
|
}
|
|
|
|
pthread_mutex_lock(&ctx->qp_table_mutex);
|
|
|
|
xparent_domain = to_xparent_domain(attr->pd);
|
|
|
|
- ret = ibv_cmd_create_qp_ex(context, &qp->verbs_qp, attr,
|
|
- &cmd.ibv_cmd, sizeof(cmd),
|
|
- &resp.ibv_resp, sizeof(resp));
|
|
+ ret = xsc_cmd_create_qp_ex(context, attr, &cmd, qp, &resp, &resp_ex);
|
|
if (ret) {
|
|
xsc_err("ibv_cmd_create_qp_ex failed,ret %d\n", ret);
|
|
errno = ret;
|
|
@@ -1108,6 +1191,9 @@ static struct ibv_qp *create_qp(struct ibv_context *context,
|
|
qp->sq.db = ctx->sqm_reg_va + (ctx->qpm_tx_db & (xdev->page_size - 1));
|
|
qp->rq.db = ctx->rqm_reg_va + (ctx->qpm_rx_db & (xdev->page_size - 1));
|
|
|
|
+ if (attr->comp_mask & IBV_QP_INIT_ATTR_SEND_OPS_FLAGS)
|
|
+ qp->verbs_qp.comp_mask |= VERBS_QP_EX;
|
|
+
|
|
return ibqp;
|
|
|
|
err_destroy:
|
|
@@ -1261,6 +1347,11 @@ int xsc_query_qp(struct ibv_qp *ibqp, struct ibv_qp_attr *attr,
|
|
init_attr->cap.max_inline_data = qp->max_inline_data;
|
|
|
|
attr->cap = init_attr->cap;
|
|
+ if (qp->err_occurred) {
|
|
+ qp->err_occurred = 0;
|
|
+ qp->ibv_qp->state = IBV_QPS_ERR;
|
|
+ attr->qp_state = IBV_QPS_ERR;
|
|
+ }
|
|
|
|
return 0;
|
|
}
|
|
diff --git a/providers/xscale/xsc_api.h b/providers/xscale/xsc_api.h
|
|
index c533019..3b3eafc 100644
|
|
--- a/providers/xscale/xsc_api.h
|
|
+++ b/providers/xscale/xsc_api.h
|
|
@@ -20,9 +20,9 @@
|
|
#define XSCDV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L3_TUNNEL XSC_IB_UAPI_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L3_TUNNEL
|
|
|
|
enum xsc_qp_create_flags {
|
|
- XSC_QP_CREATE_RAWPACKE_TSO = 1 << 0,
|
|
XSC_QP_CREATE_RAWPACKET_TSO = 1 << 0,
|
|
- XSC_QP_CREATE_RAWPACKET_TX = 1 << 1,
|
|
+ XSC_QP_CREATE_RAWPACKET_SNIFFER = 1 << 2,
|
|
+ XSC_QP_CREATE_RAWPACKET_TX = 1 << 3,
|
|
};
|
|
|
|
|
|
diff --git a/providers/xscale/xsc_hsi.h b/providers/xscale/xsc_hsi.h
|
|
index 53fe552..30887af 100644
|
|
--- a/providers/xscale/xsc_hsi.h
|
|
+++ b/providers/xscale/xsc_hsi.h
|
|
@@ -65,28 +65,50 @@ enum {
|
|
};
|
|
|
|
enum {
|
|
- XSC_ERR_CODE_NAK_RETRY = 0x40,
|
|
- XSC_ERR_CODE_NAK_OPCODE = 0x41,
|
|
- XSC_ERR_CODE_NAK_MR = 0x42,
|
|
- XSC_ERR_CODE_NAK_OPERATION = 0x43,
|
|
- XSC_ERR_CODE_NAK_RNR = 0x44,
|
|
- XSC_ERR_CODE_LOCAL_MR = 0x45,
|
|
- XSC_ERR_CODE_LOCAL_LEN = 0x46,
|
|
- XSC_ERR_CODE_LOCAL_OPCODE = 0x47,
|
|
- XSC_ERR_CODE_CQ_OVER_FLOW = 0x48,
|
|
- XSC_ERR_CODE_STRG_ACC_GEN_CQE = 0x4c,
|
|
- XSC_ERR_CODE_CQE_ACC = 0x4d,
|
|
- XSC_ERR_CODE_FLUSH = 0x4e,
|
|
- XSC_ERR_CODE_MALF_WQE_HOST = 0x50,
|
|
- XSC_ERR_CODE_MALF_WQE_INFO = 0x51,
|
|
- XSC_ERR_CODE_MR_NON_NAK = 0x52,
|
|
- XSC_ERR_CODE_OPCODE_GEN_CQE = 0x61,
|
|
- XSC_ERR_CODE_MANY_READ = 0x62,
|
|
- XSC_ERR_CODE_LEN_GEN_CQE = 0x63,
|
|
- XSC_ERR_CODE_MR = 0x65,
|
|
- XSC_ERR_CODE_MR_GEN_CQE = 0x66,
|
|
- XSC_ERR_CODE_OPERATION = 0x67,
|
|
- XSC_ERR_CODE_MALF_WQE_INFO_GEN_NAK = 0x68,
|
|
+ XSC_ANDES_ERR_CODE_NAK_RETRY = 0x40,
|
|
+ XSC_ANDES_ERR_CODE_NAK_OPCODE = 0x41,
|
|
+ XSC_ANDES_ERR_CODE_NAK_MR = 0x42,
|
|
+ XSC_ANDES_ERR_CODE_NAK_OPERATION = 0x43,
|
|
+ XSC_ANDES_ERR_CODE_NAK_RNR = 0x44,
|
|
+ XSC_ANDES_ERR_CODE_LOCAL_MR = 0x45,
|
|
+ XSC_ANDES_ERR_CODE_LOCAL_LEN = 0x46,
|
|
+ XSC_ANDES_ERR_CODE_LOCAL_OPCODE = 0x47,
|
|
+ XSC_ANDES_ERR_CODE_CQ_OVER_FLOW = 0x48,
|
|
+ XSC_ANDES_ERR_CODE_LOCAL_OPERATION_WQE = 0x49,
|
|
+ XSC_ANDES_ERR_CODE_STRG_ACC_GEN_CQE = 0x4b,
|
|
+ XSC_ANDES_ERR_CODE_STRG_ACC = 0x4c,
|
|
+ XSC_ANDES_ERR_CODE_CQE_ACC = 0x4d,
|
|
+ XSC_ANDES_ERR_CODE_FLUSH = 0x4e,
|
|
+ XSC_ANDES_ERR_CODE_MALF_WQE_HOST = 0x50,
|
|
+ XSC_ANDES_ERR_CODE_MALF_WQE_INFO = 0x51,
|
|
+ XSC_ANDES_ERR_CODE_MR_NON_NAK = 0x52,
|
|
+ XSC_ANDES_ERR_CODE_OPCODE_GEN_CQE = 0x61,
|
|
+ XSC_ANDES_ERR_CODE_MANY_READ = 0x62,
|
|
+ XSC_ANDES_ERR_CODE_LEN_GEN_CQE = 0x63,
|
|
+ XSC_ANDES_ERR_CODE_MR = 0x65,
|
|
+ XSC_ANDES_ERR_CODE_MR_GEN_CQE = 0x66,
|
|
+ XSC_ANDES_ERR_CODE_OPERATION = 0x67,
|
|
+ XSC_ANDES_ERR_CODE_MALF_WQE_INFO_GEN_NAK = 0x68,
|
|
+};
|
|
+
|
|
+enum {
|
|
+ XSC_DIAMOND_ERR_CODE_NAK_SEQ_ERR = 0xa0,
|
|
+ XSC_DIAMOND_ERR_CODE_RTO_REQ = 0xa2,
|
|
+ XSC_DIAMOND_ERR_CODE_NAK_INV_REQ = 0xa4,
|
|
+ XSC_DIAMOND_ERR_CODE_NAK_MR = 0xa5,
|
|
+ XSC_DIAMOND_ERR_CODE_NAK_REMOTE_OPER_ERR = 0xa6,
|
|
+ XSC_DIAMOND_ERR_CODE_LOCAL_MR_REQ = 0xa7,
|
|
+ XSC_DIAMOND_ERR_CODE_SND_WQE_FORMAT = 0xab,
|
|
+ XSC_DIAMOND_ERR_CODE_RCV_WQE_DMA = 0xaf,
|
|
+ XSC_DIAMOND_ERR_CODE_DATA_DMA_RD_REQ = 0xb2,
|
|
+ XSC_DIAMOND_ERR_CODE_DATA_DMA_WR_RSP_GEN_CQE = 0xb4,
|
|
+ XSC_DIAMOND_ERR_CODE_DATA_DMA_WR_RSP = 0xb5,
|
|
+ XSC_DIAMOND_ERR_CODE_LEN_GEN_CQE = 0xc4,
|
|
+ XSC_DIAMOND_ERR_CODE_LEN = 0xc5,
|
|
+ XSC_DIAMOND_ERR_CODE_REMOTE_MR = 0xd4,
|
|
+ XSC_DIAMOND_ERR_CODE_REMOTE_MR_GEN_CQE = 0xd5,
|
|
+ XSC_DIAMOND_ERR_CODE_LOCAL_MR_RSP = 0xd6,
|
|
+ XSC_DIAMOND_ERR_CODE_FLUSH = 0xff,
|
|
};
|
|
|
|
/* TODO: sw cqe opcode*/
|
|
@@ -102,6 +124,9 @@ enum {
|
|
XSC_OPCODE_RDMA_REQ_ERROR = 8,
|
|
XSC_OPCODE_RDMA_RSP_ERROR = 9,
|
|
XSC_OPCODE_RDMA_CQE_ERROR = 10,
|
|
+ XSC_OPCODE_RDMA_MAD_REQ_SEND = 11,
|
|
+ XSC_OPCODE_RDMA_MAD_RSP_RECV = 12,
|
|
+ XSC_OPCODE_RDMA_CQE_RAW_SNF = 13,
|
|
};
|
|
|
|
enum {
|
|
@@ -147,13 +172,7 @@ struct xsc_wqe_data_seg {
|
|
};
|
|
|
|
struct xsc_cqe {
|
|
- union {
|
|
- uint8_t msg_opcode;
|
|
- struct {
|
|
- uint8_t error_code:7;
|
|
- uint8_t is_error:1;
|
|
- };
|
|
- };
|
|
+ uint8_t placeholder1;
|
|
__le32 qp_id:15;
|
|
uint8_t :1;
|
|
uint8_t se:1;
|
|
@@ -166,7 +185,9 @@ struct xsc_cqe {
|
|
__le32 vni;
|
|
__le64 ts:48;
|
|
__le16 wqe_id;
|
|
- __le16 rsv[3];
|
|
+ uint8_t placeholder2;
|
|
+ uint8_t rsv2;
|
|
+ __le16 rsv[2];
|
|
__le16 rsv1:15;
|
|
uint8_t owner:1;
|
|
};
|
|
@@ -174,32 +195,10 @@ struct xsc_cqe {
|
|
/* Size of CQE */
|
|
#define XSC_CQE_SIZE sizeof(struct xsc_cqe)
|
|
|
|
-union xsc_db_data {
|
|
- struct {
|
|
- __le32 sq_next_pid:16;
|
|
- __le32 sqn:15;
|
|
- __le32 :1;
|
|
- };
|
|
- struct {
|
|
- __le32 rq_next_pid:13;
|
|
- __le32 rqn:15;
|
|
- __le32 :4;
|
|
- };
|
|
- struct {
|
|
- __le32 cq_next_cid:16;
|
|
- __le32 cqn:15;
|
|
- __le32 solicited:1;
|
|
- };
|
|
- __le32 raw_data;
|
|
-};
|
|
-
|
|
#define CQM_DB_NEXT_CID_OFFSET(n) (4 * (n))
|
|
|
|
#define XSC_SEND_WQE_RING_DEPTH_MIN 16
|
|
#define XSC_CQE_RING_DEPTH_MIN 2
|
|
-#define XSC_SEND_WQE_RING_DEPTH_MAX 1024
|
|
-#define XSC_RECV_WQE_RING_DEPTH_MAX 1024
|
|
-#define XSC_CQE_RING_DEPTH_MAX (1024 * 32)
|
|
|
|
/*
|
|
* Registers that are allocated by HW and accessed by SW in 4-byte granularity
|
|
diff --git a/providers/xscale/xscale.c b/providers/xscale/xscale.c
|
|
index e24cfd2..8b04558 100644
|
|
--- a/providers/xscale/xscale.c
|
|
+++ b/providers/xscale/xscale.c
|
|
@@ -16,12 +16,14 @@
|
|
#include <sched.h>
|
|
#include <sys/param.h>
|
|
|
|
+#include <util/mmio.h>
|
|
#include <util/symver.h>
|
|
|
|
#include "xscale.h"
|
|
#include "xsc-abi.h"
|
|
#include "wqe.h"
|
|
#include "xsc_hsi.h"
|
|
+#include "xsc_hw.h"
|
|
|
|
#ifndef CPU_OR
|
|
#define CPU_OR(x, y, z) do {} while (0)
|
|
@@ -60,7 +62,8 @@ static const struct verbs_context_ops xsc_ctx_common_ops = {
|
|
.alloc_pd = xsc_alloc_pd,
|
|
.dealloc_pd = xsc_free_pd,
|
|
.reg_mr = xsc_reg_mr,
|
|
- .rereg_mr = xsc_rereg_mr,
|
|
+ .reg_dmabuf_mr = xsc_reg_dmabuf_mr,
|
|
+ .rereg_mr = NULL,
|
|
.dereg_mr = xsc_dereg_mr,
|
|
.alloc_mw = NULL,
|
|
.dealloc_mw = NULL,
|
|
@@ -417,6 +420,10 @@ static void xsc_read_env(struct ibv_device *ibdev, struct xsc_context *ctx)
|
|
ctx->stall_cycles = xsc_stall_cq_poll_min;
|
|
}
|
|
|
|
+ env_value = getenv("XSC_POST_RECV_DUMP_WQE");
|
|
+ if (env_value)
|
|
+ xsc_post_recv_dump_wqe = (strcmp(env_value, "0")) ? 1 : 0;
|
|
+
|
|
}
|
|
|
|
static void open_debug_file(struct xsc_context *ctx)
|
|
@@ -787,6 +794,7 @@ static void xsc_munmap(struct xsc_context *context)
|
|
munmap(context->cqm_armdb_va, context->db_mmap_size);
|
|
|
|
}
|
|
+
|
|
static struct verbs_context *xsc_alloc_context(struct ibv_device *ibdev,
|
|
int cmd_fd,
|
|
void *private_data)
|
|
@@ -845,6 +853,7 @@ static struct verbs_context *xsc_alloc_context(struct ibv_device *ibdev,
|
|
context->send_ds_shift = xsc_ilog2(resp.send_ds_num);
|
|
context->recv_ds_num = resp.recv_ds_num;
|
|
context->recv_ds_shift = xsc_ilog2(resp.recv_ds_num);
|
|
+ context->device_id = resp.device_id;
|
|
|
|
xsc_dbg(context->dbg_fp, XSC_DBG_CTX,
|
|
"max_num_qps:%u, max_sq_desc_sz:%u max_rq_desc_sz:%u " \
|
|
@@ -894,6 +903,7 @@ static struct verbs_context *xsc_alloc_context(struct ibv_device *ibdev,
|
|
context->atomic_cap = device_attr.orig_attr.atomic_cap;
|
|
context->cached_tso_caps = device_attr.tso_caps;
|
|
context->max_dm_size = device_attr.max_dm_size;
|
|
+ context->max_cqe = device_attr.orig_attr.max_cqe;
|
|
}
|
|
|
|
for (j = 0; j < min(XSC_MAX_PORTS_NUM, context->num_ports); ++j) {
|
|
diff --git a/providers/xscale/xscale.h b/providers/xscale/xscale.h
|
|
index c6cc9f7..e837e9b 100644
|
|
--- a/providers/xscale/xscale.h
|
|
+++ b/providers/xscale/xscale.h
|
|
@@ -45,6 +45,7 @@ enum {
|
|
enum {
|
|
XSC_QP_FLAG_RAWPACKET_TSO = 1 << 9,
|
|
XSC_QP_FLAG_RAWPACKET_TX = 1 << 10,
|
|
+ XSC_QP_FLAG_RAWPACKET_SNIFFER = 1 << 11,
|
|
};
|
|
|
|
|
|
@@ -66,6 +67,7 @@ enum {
|
|
XSC_DBG_CTX = 1 << 7,
|
|
XSC_DBG_PD = 1 << 8,
|
|
XSC_DBG_MR = 1 << 9,
|
|
+ XSC_DBG_QP_RECV = 1 << 10,
|
|
};
|
|
|
|
extern uint32_t xsc_debug_mask;
|
|
@@ -75,7 +77,7 @@ extern int xsc_freeze_on_error_cqe;
|
|
#ifdef XSC_DEBUG
|
|
#define xsc_dbg(fp, mask, fmt, args...) \
|
|
do { \
|
|
- if (xsc_debug_mask & mask) { \
|
|
+ if (unlikely(xsc_debug_mask & mask)) { \
|
|
char host[256]; \
|
|
char timestr[32]; \
|
|
struct tm now_tm; \
|
|
@@ -246,6 +248,7 @@ struct xsc_context {
|
|
struct xsc_packet_pacing_caps packet_pacing_caps;
|
|
uint16_t flow_action_flags;
|
|
uint64_t max_dm_size;
|
|
+ uint32_t max_cqe;
|
|
uint32_t eth_min_inline_size;
|
|
uint32_t dump_fill_mkey;
|
|
__be32 dump_fill_mkey_be;
|
|
@@ -264,6 +267,7 @@ struct xsc_context {
|
|
uint32_t send_ds_shift;
|
|
uint32_t recv_ds_shift;
|
|
FILE *dbg_fp;
|
|
+ uint16_t device_id;
|
|
};
|
|
|
|
struct xsc_bitmap {
|
|
@@ -343,7 +347,7 @@ struct xsc_cq {
|
|
int stall_adaptive_enable;
|
|
int stall_cycles;
|
|
struct xsc_resource *cur_rsc;
|
|
- struct xsc_cqe64 *cqe64;
|
|
+ struct xsc_cqe *cqe;
|
|
uint32_t flags;
|
|
int umr_opcode;
|
|
struct xscdv_clock_info last_clock_info;
|
|
@@ -387,7 +391,6 @@ struct xsc_dm {
|
|
|
|
struct xsc_mr {
|
|
struct verbs_mr vmr;
|
|
- struct xsc_buf buf;
|
|
uint32_t alloc_flags;
|
|
};
|
|
|
|
@@ -408,6 +411,17 @@ struct xsc_qp {
|
|
struct xsc_buf sq_buf;
|
|
int sq_buf_size;
|
|
|
|
+ int err;
|
|
+ /* Number of WR entries posted in the current wr session */
|
|
+ int nreq;
|
|
+ uint32_t cur_post_rb;
|
|
+ void *cur_ctrl;
|
|
+ void *cur_data;
|
|
+ int cur_ds_num;
|
|
+ uint32_t cur_data_len;
|
|
+ uint64_t cur_remote_addr;
|
|
+ uint32_t cur_remote_key;
|
|
+
|
|
uint8_t fm_cache;
|
|
uint8_t sq_signal_bits;
|
|
struct xsc_wq sq;
|
|
@@ -426,6 +440,7 @@ struct xsc_qp {
|
|
uint32_t tisn;
|
|
uint32_t rqn;
|
|
uint32_t sqn;
|
|
+ unsigned int err_occurred;
|
|
};
|
|
|
|
struct xsc_ah {
|
|
@@ -514,6 +529,7 @@ extern int xsc_stall_cq_poll_max;
|
|
extern int xsc_stall_cq_inc_step;
|
|
extern int xsc_stall_cq_dec_step;
|
|
extern int xsc_single_threaded;
|
|
+extern int xsc_post_recv_dump_wqe;
|
|
|
|
static inline unsigned DIV_ROUND_UP(unsigned n, unsigned d)
|
|
{
|
|
@@ -658,6 +674,8 @@ int xsc_free_pd(struct ibv_pd *pd);
|
|
struct ibv_mr *xsc_alloc_null_mr(struct ibv_pd *pd);
|
|
struct ibv_mr *xsc_reg_mr(struct ibv_pd *pd, void *addr,
|
|
size_t length, uint64_t hca_va, int access);
|
|
+struct ibv_mr *xsc_reg_dmabuf_mr(struct ibv_pd *pd, uint64_t offset, size_t length,
|
|
+ uint64_t iova, int fd, int acc);
|
|
int xsc_rereg_mr(struct verbs_mr *mr, int flags, struct ibv_pd *pd, void *addr,
|
|
size_t length, int access);
|
|
int xsc_dereg_mr(struct verbs_mr *mr);
|
|
@@ -666,9 +684,8 @@ struct ibv_cq *xsc_create_cq(struct ibv_context *context, int cqe,
|
|
int comp_vector);
|
|
struct ibv_cq_ex *xsc_create_cq_ex(struct ibv_context *context,
|
|
struct ibv_cq_init_attr_ex *cq_attr);
|
|
-int xsc_cq_fill_pfns(struct xsc_cq *cq,
|
|
- const struct ibv_cq_init_attr_ex *cq_attr,
|
|
- struct xsc_context *xctx);
|
|
+void xsc_cq_fill_pfns(struct xsc_cq *cq,
|
|
+ const struct ibv_cq_init_attr_ex *cq_attr);
|
|
int xsc_alloc_cq_buf(struct xsc_context *xctx, struct xsc_cq *cq,
|
|
struct xsc_buf *buf, int nent, int cqe_sz);
|
|
int xsc_free_cq_buf(struct xsc_context *ctx, struct xsc_buf *buf);
|
|
@@ -710,7 +727,6 @@ int xsc_destroy_ah(struct ibv_ah *ah);
|
|
int xsc_attach_mcast(struct ibv_qp *qp, const union ibv_gid *gid, uint16_t lid);
|
|
int xsc_detach_mcast(struct ibv_qp *qp, const union ibv_gid *gid, uint16_t lid);
|
|
int xsc_round_up_power_of_two(long long sz);
|
|
-void *xsc_get_send_wqe(struct xsc_qp *qp, int n);
|
|
struct ibv_xrcd *xsc_open_xrcd(struct ibv_context *context,
|
|
struct ibv_xrcd_init_attr *xrcd_init_attr);
|
|
int xsc_close_xrcd(struct ibv_xrcd *ib_xrcd);
|
|
@@ -750,7 +766,7 @@ int xsc_read_counters(struct ibv_counters *counters,
|
|
uint64_t *counters_value,
|
|
uint32_t ncounters,
|
|
uint32_t flags);
|
|
-
|
|
+int xsc_qp_fill_wr_pfns(struct xsc_qp *xqp, const struct ibv_qp_init_attr_ex *attr);
|
|
static inline void *xsc_find_uidx(struct xsc_context *ctx, uint32_t uidx)
|
|
{
|
|
int tind = uidx >> XSC_UIDX_TABLE_SHIFT;
|
|
@@ -849,4 +865,9 @@ static inline uint8_t calc_sig(void *wqe, int size)
|
|
return ~res;
|
|
}
|
|
|
|
+static inline void *xsc_get_send_wqe(struct xsc_qp *qp, int n)
|
|
+{
|
|
+ return qp->sq_start + (n << qp->sq.wqe_shift);
|
|
+}
|
|
+
|
|
#endif /* XSC_H */
|
|
--
|
|
2.43.0
|
|
|