diff mbox series

[rdma-core,1/5] RDMA-CORE/erdma: Add userspace verbs related header files.

Message ID 20211224065522.29734-2-chengyou@linux.alibaba.com (mailing list archive)
State Not Applicable
Headers show
Series Elastic RDMA Adapter (ERDMA) userspace provider driver | expand

Commit Message

Cheng Xu Dec. 24, 2021, 6:55 a.m. UTC
Add the userspace verbs implementation related header files: 'erdma_hw.h'
for hardware interface definitions, 'erdma_verbs.h' for verbs related
definitions and 'erdma_db.h' for doorbell records related definitions.

Signed-off-by: Cheng Xu <chengyou@linux.alibaba.com>
---
 providers/erdma/erdma_db.h    |  17 +++
 providers/erdma/erdma_hw.h    | 206 ++++++++++++++++++++++++++++++++++
 providers/erdma/erdma_verbs.h | 134 ++++++++++++++++++++++
 3 files changed, 357 insertions(+)
 create mode 100644 providers/erdma/erdma_db.h
 create mode 100644 providers/erdma/erdma_hw.h
 create mode 100644 providers/erdma/erdma_verbs.h

Comments

Devesh Sharma Dec. 27, 2021, 5:48 a.m. UTC | #1
> -----Original Message-----
> From: Cheng Xu <chengyou@linux.alibaba.com>
> Sent: Friday, December 24, 2021 12:25 PM
> To: leon@kernel.org
> Cc: dledford@redhat.com; jgg@mellanox.com; linux-rdma@vger.kernel.org;
> KaiShen@linux.alibaba.com; chengyou@linux.alibaba.com
> Subject: [PATCH rdma-core 1/5] RDMA-CORE/erdma: Add userspace verbs
> related header files.
> 
> Add the userspace verbs implementation related header files: 'erdma_hw.h'
> for hardware interface definitions, 'erdma_verbs.h' for verbs related
> definitions and 'erdma_db.h' for doorbell records related definitions.
> 
> Signed-off-by: Cheng Xu <chengyou@linux.alibaba.com>
> ---
>  providers/erdma/erdma_db.h    |  17 +++
>  providers/erdma/erdma_hw.h    | 206
> ++++++++++++++++++++++++++++++++++
>  providers/erdma/erdma_verbs.h | 134 ++++++++++++++++++++++
>  3 files changed, 357 insertions(+)
>  create mode 100644 providers/erdma/erdma_db.h  create mode 100644
> providers/erdma/erdma_hw.h  create mode 100644
> providers/erdma/erdma_verbs.h
> 
> diff --git a/providers/erdma/erdma_db.h b/providers/erdma/erdma_db.h
> new file mode 100644 index 00000000..c302cb7a
> --- /dev/null
> +++ b/providers/erdma/erdma_db.h
> @@ -0,0 +1,17 @@
> +/* SPDX-License-Identifier: GPL-2.0 or OpenIB.org BSD (MIT) See COPYING
> +file */
> +/*
> + * Authors: Cheng Xu <chengyou@linux.alibaba.com>
> + * Copyright (c) 2020-2021, Alibaba Group.
> + */
> +
> +#ifndef __ERDMA_DB_H__
> +#define __ERDMA_DB_H__
> +
> +#include <inttypes.h>
> +
> +#include "erdma.h"
> +
> +uint64_t *erdma_alloc_dbrecords(struct erdma_context *ctx); void
> +erdma_dealloc_dbrecords(struct erdma_context *ctx, uint64_t
> +*dbrecords);
> +
> +#endif
> diff --git a/providers/erdma/erdma_hw.h b/providers/erdma/erdma_hw.h
> new file mode 100644 index 00000000..f373f7f8
> --- /dev/null
> +++ b/providers/erdma/erdma_hw.h
> @@ -0,0 +1,206 @@
> +/* SPDX-License-Identifier: GPL-2.0 or OpenIB.org BSD (MIT) See COPYING
> +file */
> +/*
> + * Authors: Cheng Xu <chengyou@linux.alibaba.com>
> + * Copyright (c) 2020-2021, Alibaba Group.
> + */
> +
> +#ifndef __ERDMA_HW_H__
> +#define __ERDMA_HW_H__
> +
> +#include <stdint.h>
> +
> +#define ERDMA_SDB_PAGE     0
> +#define ERDMA_SDB_ENTRY    1
> +#define ERDMA_SDB_SHARED   2
> +
> +#define ERDMA_SQDB_SIZE 128
> +#define ERDMA_CQDB_SIZE 8
> +#define ERDMA_RQDB_SIZE 8
> +#define ERDMA_RQDB_SPACE_SIZE   32
> +
> +/* WQE related. */
> +#define EQE_SIZE 16
> +#define EQE_SHIFT 4
> +#define RQE_SIZE 32
> +#define RQE_SHIFT 5
> +#define CQE_SIZE 32
> +#define CQE_SHIFT 5
> +#define SQEBB_SIZE 32
> +#define SQEBB_SHIFT 5
> +#define SQEBB_MASK (~(SQEBB_SIZE - 1))
> +#define SQEBB_ALIGN(size) ((size + SQEBB_SIZE - 1) & SQEBB_MASK)
> +#define SQEBB_COUNT(size) (SQEBB_ALIGN(size) >> SQEBB_SHIFT)
> +
> +#define MAX_WQEBB_PER_SQE 4
> +
> +enum erdma_opcode {
> +	ERDMA_OP_WRITE           = 0,
> +	ERDMA_OP_READ            = 1,
> +	ERDMA_OP_SEND            = 2,
> +	ERDMA_OP_SEND_WITH_IMM   = 3,
> +
> +	ERDMA_OP_RECEIVE         = 4,
> +	ERDMA_OP_RECV_IMM        = 5,
> +	ERDMA_OP_RECV_INV        = 6,
> +
> +	ERDMA_OP_REQ_ERR         = 7,
> +	ERDNA_OP_READ_RESPONSE   = 8,
> +	ERDMA_OP_WRITE_WITH_IMM  = 9,
> +
> +	ERDMA_OP_RECV_ERR        = 10,
> +
> +	ERDMA_OP_INVALIDATE     = 11,
> +	ERDMA_OP_RSP_SEND_IMM   = 12,
> +	ERDMA_OP_SEND_WITH_INV  = 13,
> +
> +	ERDMA_OP_REG_MR         = 14,
> +	ERDMA_OP_LOCAL_INV      = 15,
> +	ERDMA_OP_READ_WITH_INV  = 16,
> +	ERDMA_NUM_OPCODES       = 17,
> +	ERDMA_OP_INVALID        = ERDMA_NUM_OPCODES + 1
> +};
> +
> +/*
> + * Inline data are kept within the work request itself occupying
> + * the space of sge[1] .. sge[n]. Therefore, inline data cannot be
> + * supported if ERDMA_MAX_SGE is below 2 elements.
> + */
> +#define ERDMA_MAX_INLINE	(sizeof(struct erdma_sge) *
> (ERDMA_MAX_SEND_SGE))
> +
> +enum erdma_wc_status {
> +	ERDMA_WC_SUCCESS = 0,
> +	ERDMA_WC_GENERAL_ERR = 1,
> +	ERDMA_WC_RECV_WQE_FORMAT_ERR = 2,
> +	ERDMA_WC_RECV_STAG_INVALID_ERR = 3,
> +	ERDMA_WC_RECV_ADDR_VIOLATION_ERR = 4,
> +	ERDMA_WC_RECV_RIGHT_VIOLATION_ERR = 5,
> +	ERDMA_WC_RECV_PDID_ERR = 6,
> +	ERDMA_WC_RECV_WARRPING_ERR = 7,
> +	ERDMA_WC_SEND_WQE_FORMAT_ERR = 8,
> +	ERDMA_WC_SEND_WQE_ORD_EXCEED = 9,
> +	ERDMA_WC_SEND_STAG_INVALID_ERR = 10,
> +	ERDMA_WC_SEND_ADDR_VIOLATION_ERR = 11,
> +	ERDMA_WC_SEND_RIGHT_VIOLATION_ERR = 12,
> +	ERDMA_WC_SEND_PDID_ERR = 13,
> +	ERDMA_WC_SEND_WARRPING_ERR = 14,
> +	ERDMA_WC_FLUSH_ERR = 15,
> +	ERDMA_WC_RETRY_EXC_ERR = 16,
> +	ERDMA_NUM_WC_STATUS
> +};
> +
> +enum erdma_vendor_err {
> +	ERDMA_WC_VENDOR_NO_ERR = 0,
> +	ERDMA_WC_VENDOR_INVALID_RQE = 1,
> +	ERDMA_WC_VENDOR_RQE_INVALID_STAG = 2,
> +	ERDMA_WC_VENDOR_RQE_ADDR_VIOLATION = 3,
> +	ERDMA_WC_VENDOR_RQE_ACCESS_RIGHT_ERR = 4,
> +	ERDMA_WC_VENDOR_RQE_INVALID_PD = 5,
> +	ERDMA_WC_VENDOR_RQE_WRAP_ERR = 6,
> +	ERDMA_WC_VENDOR_INVALID_SQE = 0x20,
> +	ERDMA_WC_VENDOR_ZERO_ORD = 0x21,
> +	ERDMA_WC_VENDOR_SQE_INVALID_STAG = 0x30,
> +	ERDMA_WC_VENDOR_SQE_ADDR_VIOLATION = 0x31,
> +	ERDMA_WC_VENDOR_SQE_ACCESS_ERR = 0x32,
> +	ERDMA_WC_VENDOR_SQE_INVALID_PD = 0x33,
> +	ERDMA_WC_VENDOR_SQE_WARP_ERR = 0x34
> +};
> +
> +
> +/* Doorbell related. */
> +#define ERDMA_CQDB_EQN_MASK              GENMASK_ULL(63, 56)
> +#define ERDMA_CQDB_CQN_MASK              GENMASK_ULL(55, 32)
> +#define ERDMA_CQDB_ARM_MASK              BIT_ULL(31)
> +#define ERDMA_CQDB_SOL_MASK              BIT_ULL(30)
> +#define ERDMA_CQDB_CMDSN_MASK            GENMASK_ULL(29, 28)
> +#define ERDMA_CQDB_CI_MASK               GENMASK_ULL(23, 0)
> +
> +#define ERDMA_CQE_QTYPE_SQ    0
> +#define ERDMA_CQE_QTYPE_RQ    1
> +#define ERDMA_CQE_QTYPE_CMDQ  2
> +
> +/* CQE hdr */
> +#define ERDMA_CQE_HDR_OWNER_MASK         BIT(31)
> +#define ERDMA_CQE_HDR_OPCODE_MASK        GENMASK(23, 16)
> +#define ERDMA_CQE_HDR_QTYPE_MASK         GENMASK(15, 8)
> +#define ERDMA_CQE_HDR_SYNDROME_MASK      GENMASK(7, 0)
> +
> +#define ERDMA_CQE_QTYPE_SQ    0
> +#define ERDMA_CQE_QTYPE_RQ    1
> +#define ERDMA_CQE_QTYPE_CMDQ  2
> +
> +
> +struct erdma_cqe {
> +	__be32 hdr;
> +	__be32 qe_idx;
> +	__be32 qpn;
> +	__le32 imm_data;
> +	__be32 size;
> +	__be32 rsvd[3];
> +};
> +
> +struct erdma_sge {
> +	__aligned_le64 laddr;
> +	__le32 length;
> +	__le32 lkey;
> +};
> +
> +/* Receive Queue Element */
> +struct erdma_rqe {
> +	__le16 qe_idx;
> +	__le16 rsvd;
> +	__le32 qpn;
> +	__le32 rsvd2;
> +	__le32 rsvd3;
> +	__le64 to;
> +	__le32 length;
> +	__le32 stag;
> +};
> +
> +/* SQE */
> +#define ERDMA_SQE_HDR_SGL_LEN_MASK       GENMASK_ULL(63, 56)
> +#define ERDMA_SQE_HDR_WQEBB_CNT_MASK     GENMASK_ULL(54, 52)
> +#define ERDMA_SQE_HDR_QPN_MASK           GENMASK_ULL(51, 32)
> +#define ERDMA_SQE_HDR_OPCODE_MASK        GENMASK_ULL(31, 27)
> +#define ERDMA_SQE_HDR_DWQE_MASK          BIT_ULL(26)
> +#define ERDMA_SQE_HDR_INLINE_MASK        BIT_ULL(25)
> +#define ERDMA_SQE_HDR_FENCE_MASK         BIT_ULL(24)
> +#define ERDMA_SQE_HDR_SE_MASK            BIT_ULL(23)
> +#define ERDMA_SQE_HDR_CE_MASK            BIT_ULL(22)
> +#define ERDMA_SQE_HDR_WQEBB_INDEX_MASK   GENMASK_ULL(15, 0)
> +
> +struct erdma_write_sqe {
> +	__le64 hdr;
> +	__be32 imm_data;
> +	__le32 length;
> +
> +	__le32 sink_stag;
> +	/* avoid sink_to not 8-byte aligned. */
> +	__le32 sink_to_low;
> +	__le32 sink_to_high;
> +
> +	__le32 rsvd;
> +
> +	struct erdma_sge sgl[0];
> +};
> +
> +struct erdma_send_sqe {
> +	__le64 hdr;
> +	__be32 imm_data;
> +	__le32 length;
> +	struct erdma_sge sgl[0];
> +};
> +
> +struct erdma_readreq_sqe {
> +	__le64 hdr;
> +	__le32 invalid_stag;
> +	__le32 length;
> +	__le32 sink_stag;
> +	/* avoid sink_to not 8-byte aligned. */
> +	__le32 sink_to_low;
> +	__le32 sink_to_high;
> +	__le32 rsvd0;
> +	struct erdma_sge sgl;
> +};
> +
> +
> +#endif
> diff --git a/providers/erdma/erdma_verbs.h
> b/providers/erdma/erdma_verbs.h new file mode 100644 index
> 00000000..944d29f5
> --- /dev/null
> +++ b/providers/erdma/erdma_verbs.h
> @@ -0,0 +1,134 @@
> +/* SPDX-License-Identifier: GPL-2.0 or OpenIB.org BSD (MIT) See COPYING
> +file */
> +/*
> + * Authors: Cheng Xu <chengyou@linux.alibaba.com>
> + * Copyright (c) 2020-2021, Alibaba Group.
> + */
> +
> +#ifndef __ERDMA_VERBS_H__
> +#define __ERDMA_VERBS_H__
> +
> +#include <pthread.h>
> +#include <inttypes.h>
> +#include <stddef.h>
> +
> +#include "erdma.h"
> +#include "erdma_hw.h"
> +
> +#define ERDMA_MAX_SEND_SGE 6
> +#define ERDMA_MAX_RECV_SGE 1
> +
> +struct erdma_queue {
> +	void *qbuf;
> +	void *db;
> +
> +	uint16_t rsvd0;
> +	uint16_t depth;
> +	uint32_t size;
> +
> +	uint16_t pi;
> +	uint16_t ci;
> +
> +	uint32_t rsvd1;
> +	uint64_t *wr_tbl;
> +
> +	void *db_record;
> +};
> +
> +struct erdma_qp {
> +	struct ibv_qp base_qp;
> +	struct erdma_device *erdma_dev;
> +
> +	uint32_t id;  /* qpn */
> +
> +	pthread_spinlock_t sq_lock;
> +	pthread_spinlock_t rq_lock;
> +
> +	int sq_sig_all;
> +
> +	struct erdma_queue sq;
> +	struct erdma_queue rq;
> +
> +	void *qbuf;
> +	uint64_t *db_records;
> +};
> +
> +struct erdma_cq {
> +	struct ibv_cq base_cq;
> +	struct erdma_device *erdma_dev;
> +	uint32_t id;
> +
> +	uint32_t event_stats;
> +
> +	uint32_t depth;
> +	uint32_t ci;
> +	uint32_t owner;
> +	struct erdma_cqe *queue;
> +
> +	void *db;
> +	uint16_t db_offset;
> +
> +	void *db_record;
> +	uint32_t cmdsn;
> +	int comp_vector;
> +
> +	pthread_spinlock_t lock;
> +};
> +
> +static inline struct erdma_qp *to_eqp(struct ibv_qp *base) {
> +	return container_of(base, struct erdma_qp, base_qp); }
> +
> +static inline struct erdma_cq *to_ecq(struct ibv_cq *base) {
> +	return container_of(base, struct erdma_cq, base_cq); }
> +
> +static inline void *get_sq_wqebb(struct erdma_qp *qp, uint16_t idx) {
> +	idx &= (qp->sq.depth - 1);
> +	return qp->sq.qbuf + (idx << SQEBB_SHIFT); }
> +
> +static inline void __kick_sq_db(struct erdma_qp *qp, uint16_t pi) {
> +	uint64_t db_data;
> +
> +	db_data = FIELD_PREP(ERDMA_SQE_HDR_QPN_MASK, qp->id) |
> +		FIELD_PREP(ERDMA_SQE_HDR_WQEBB_INDEX_MASK, pi);
> +
> +	*(__le64 *)qp->sq.db_record = htole64(db_data);
> +	udma_to_device_barrier();
> +	mmio_write64_le(qp->sq.db, htole64(db_data)); }
Standard function definition format
Func ()
{

}
Update all over the place.
> +
> +struct ibv_pd *erdma_alloc_pd(struct ibv_context *ctx); int
> +erdma_free_pd(struct ibv_pd *pd);
> +
> +int erdma_query_device(struct ibv_context *ctx,
> +		       const struct ibv_query_device_ex_input *input,
> +		       struct ibv_device_attr_ex *attr, size_t attr_size); int
> +erdma_query_port(struct ibv_context *ctx, uint8_t port, struct
> +ibv_port_attr *attr);
> +
> +struct ibv_mr *erdma_reg_mr(struct ibv_pd *pd, void *addr, size_t len,
> +			    uint64_t hca_va, int access);
> +int erdma_dereg_mr(struct verbs_mr *vmr);
> +
> +struct ibv_qp *erdma_create_qp(struct ibv_pd *pd, struct
> +ibv_qp_init_attr *attr); int erdma_modify_qp(struct ibv_qp *base_qp,
> +struct ibv_qp_attr *attr, int attr_mask); int erdma_query_qp(struct ibv_qp
> *qp, struct ibv_qp_attr *attr,
> +		   int attr_mask, struct ibv_qp_init_attr *init_attr); int
> +erdma_post_send(struct ibv_qp *base_qp, struct ibv_send_wr *wr, struct
> +ibv_send_wr **bad_wr); int erdma_post_recv(struct ibv_qp *base_qp,
> +struct ibv_recv_wr *wr, struct ibv_recv_wr **bad_wr); int
> +erdma_destroy_qp(struct ibv_qp *base_qp);
> +
> +void erdma_free_context(struct ibv_context *ibv_ctx);
> +
> +struct ibv_cq *erdma_create_cq(struct ibv_context *ctx, int num_cqe,
> +			       struct ibv_comp_channel *channel, int
> comp_vector); int
> +erdma_destroy_cq(struct ibv_cq *base_cq); int erdma_notify_cq(struct
> +ibv_cq *ibcq, int solicited); void erdma_cq_event(struct ibv_cq *ibcq);
> +int erdma_poll_cq(struct ibv_cq *ibcq, int num_entries, struct ibv_wc
> +*wc);
> +
> +#endif
> --
> 2.27.0
Cheng Xu Dec. 27, 2021, 6:46 a.m. UTC | #2
On 12/27/21 1:48 PM, Devesh Sharma wrote:
> 
> 
<...>

>> +
>> +static inline struct erdma_qp *to_eqp(struct ibv_qp *base) {
>> +	return container_of(base, struct erdma_qp, base_qp); }
>> +
>> +static inline struct erdma_cq *to_ecq(struct ibv_cq *base) {
>> +	return container_of(base, struct erdma_cq, base_cq); }
>> +
>> +static inline void *get_sq_wqebb(struct erdma_qp *qp, uint16_t idx) {
>> +	idx &= (qp->sq.depth - 1);
>> +	return qp->sq.qbuf + (idx << SQEBB_SHIFT); }
>> +
>> +static inline void __kick_sq_db(struct erdma_qp *qp, uint16_t pi) {
>> +	uint64_t db_data;
>> +
>> +	db_data = FIELD_PREP(ERDMA_SQE_HDR_QPN_MASK, qp->id) |
>> +		FIELD_PREP(ERDMA_SQE_HDR_WQEBB_INDEX_MASK, pi);
>> +
>> +	*(__le64 *)qp->sq.db_record = htole64(db_data);
>> +	udma_to_device_barrier();
>> +	mmio_write64_le(qp->sq.db, htole64(db_data)); }
> Standard function definition format
> Func ()
> {
> 
> }
> Update all over the place.

OK, I will fix it.

Thanks,
Cheng Xu

>> --
>> 2.27.0
Jason Gunthorpe Jan. 3, 2022, 11:52 p.m. UTC | #3
On Mon, Dec 27, 2021 at 02:46:49PM +0800, Cheng Xu wrote:

> > > +static inline struct erdma_qp *to_eqp(struct ibv_qp *base) {
> > > +	return container_of(base, struct erdma_qp, base_qp); }
> > > +
> > > +static inline struct erdma_cq *to_ecq(struct ibv_cq *base) {
> > > +	return container_of(base, struct erdma_cq, base_cq); }
> > > +
> > > +static inline void *get_sq_wqebb(struct erdma_qp *qp, uint16_t idx) {
> > > +	idx &= (qp->sq.depth - 1);
> > > +	return qp->sq.qbuf + (idx << SQEBB_SHIFT); }
> > > +
> > > +static inline void __kick_sq_db(struct erdma_qp *qp, uint16_t pi) {
> > > +	uint64_t db_data;
> > > +
> > > +	db_data = FIELD_PREP(ERDMA_SQE_HDR_QPN_MASK, qp->id) |
> > > +		FIELD_PREP(ERDMA_SQE_HDR_WQEBB_INDEX_MASK, pi);
> > > +
> > > +	*(__le64 *)qp->sq.db_record = htole64(db_data);
> > > +	udma_to_device_barrier();
> > > +	mmio_write64_le(qp->sq.db, htole64(db_data)); }
> > Standard function definition format
> > Func ()
> > {
> > 
> > }
> > Update all over the place.
> 
> OK, I will fix it.

Run it all through clang-format. Very little should deviate from
clang-format, use your best judgement in special formatting cases.

Jason
Cheng Xu Jan. 5, 2022, 1:55 a.m. UTC | #4
On 1/4/22 7:52 AM, Jason Gunthorpe wrote:
> On Mon, Dec 27, 2021 at 02:46:49PM +0800, Cheng Xu wrote:
> 
>>>> +static inline struct erdma_qp *to_eqp(struct ibv_qp *base) {
>>>> +	return container_of(base, struct erdma_qp, base_qp); }
>>>> +
>>>> +static inline struct erdma_cq *to_ecq(struct ibv_cq *base) {
>>>> +	return container_of(base, struct erdma_cq, base_cq); }
>>>> +
>>>> +static inline void *get_sq_wqebb(struct erdma_qp *qp, uint16_t idx) {
>>>> +	idx &= (qp->sq.depth - 1);
>>>> +	return qp->sq.qbuf + (idx << SQEBB_SHIFT); }
>>>> +
>>>> +static inline void __kick_sq_db(struct erdma_qp *qp, uint16_t pi) {
>>>> +	uint64_t db_data;
>>>> +
>>>> +	db_data = FIELD_PREP(ERDMA_SQE_HDR_QPN_MASK, qp->id) |
>>>> +		FIELD_PREP(ERDMA_SQE_HDR_WQEBB_INDEX_MASK, pi);
>>>> +
>>>> +	*(__le64 *)qp->sq.db_record = htole64(db_data);
>>>> +	udma_to_device_barrier();
>>>> +	mmio_write64_le(qp->sq.db, htole64(db_data)); }
>>> Standard function definition format
>>> Func ()
>>> {
>>>
>>> }
>>> Update all over the place.
>>
>> OK, I will fix it.
> 
> Run it all through clang-format. Very little should deviate from
> clang-format, use your best judgement in special formatting cases.
> 
> Jason

Very useful, thanks.

Cheng Xu
diff mbox series

Patch

diff --git a/providers/erdma/erdma_db.h b/providers/erdma/erdma_db.h
new file mode 100644
index 00000000..c302cb7a
--- /dev/null
+++ b/providers/erdma/erdma_db.h
@@ -0,0 +1,17 @@ 
+/* SPDX-License-Identifier: GPL-2.0 or OpenIB.org BSD (MIT) See COPYING file */
+/*
+ * Authors: Cheng Xu <chengyou@linux.alibaba.com>
+ * Copyright (c) 2020-2021, Alibaba Group.
+ */
+
+#ifndef __ERDMA_DB_H__
+#define __ERDMA_DB_H__
+
+#include <inttypes.h>
+
+#include "erdma.h"
+
+uint64_t *erdma_alloc_dbrecords(struct erdma_context *ctx);
+void erdma_dealloc_dbrecords(struct erdma_context *ctx, uint64_t *dbrecords);
+
+#endif
diff --git a/providers/erdma/erdma_hw.h b/providers/erdma/erdma_hw.h
new file mode 100644
index 00000000..f373f7f8
--- /dev/null
+++ b/providers/erdma/erdma_hw.h
@@ -0,0 +1,206 @@ 
+/* SPDX-License-Identifier: GPL-2.0 or OpenIB.org BSD (MIT) See COPYING file */
+/*
+ * Authors: Cheng Xu <chengyou@linux.alibaba.com>
+ * Copyright (c) 2020-2021, Alibaba Group.
+ */
+
+#ifndef __ERDMA_HW_H__
+#define __ERDMA_HW_H__
+
+#include <stdint.h>
+
+#define ERDMA_SDB_PAGE     0
+#define ERDMA_SDB_ENTRY    1
+#define ERDMA_SDB_SHARED   2
+
+#define ERDMA_SQDB_SIZE 128
+#define ERDMA_CQDB_SIZE 8
+#define ERDMA_RQDB_SIZE 8
+#define ERDMA_RQDB_SPACE_SIZE   32
+
+/* WQE related. */
+#define EQE_SIZE 16
+#define EQE_SHIFT 4
+#define RQE_SIZE 32
+#define RQE_SHIFT 5
+#define CQE_SIZE 32
+#define CQE_SHIFT 5
+#define SQEBB_SIZE 32
+#define SQEBB_SHIFT 5
+#define SQEBB_MASK (~(SQEBB_SIZE - 1))
+#define SQEBB_ALIGN(size) ((size + SQEBB_SIZE - 1) & SQEBB_MASK)
+#define SQEBB_COUNT(size) (SQEBB_ALIGN(size) >> SQEBB_SHIFT)
+
+#define MAX_WQEBB_PER_SQE 4
+
+enum erdma_opcode {
+	ERDMA_OP_WRITE           = 0,
+	ERDMA_OP_READ            = 1,
+	ERDMA_OP_SEND            = 2,
+	ERDMA_OP_SEND_WITH_IMM   = 3,
+
+	ERDMA_OP_RECEIVE         = 4,
+	ERDMA_OP_RECV_IMM        = 5,
+	ERDMA_OP_RECV_INV        = 6,
+
+	ERDMA_OP_REQ_ERR         = 7,
+	ERDNA_OP_READ_RESPONSE   = 8,
+	ERDMA_OP_WRITE_WITH_IMM  = 9,
+
+	ERDMA_OP_RECV_ERR        = 10,
+
+	ERDMA_OP_INVALIDATE     = 11,
+	ERDMA_OP_RSP_SEND_IMM   = 12,
+	ERDMA_OP_SEND_WITH_INV  = 13,
+
+	ERDMA_OP_REG_MR         = 14,
+	ERDMA_OP_LOCAL_INV      = 15,
+	ERDMA_OP_READ_WITH_INV  = 16,
+	ERDMA_NUM_OPCODES       = 17,
+	ERDMA_OP_INVALID        = ERDMA_NUM_OPCODES + 1
+};
+
+/*
+ * Inline data are kept within the work request itself occupying
+ * the space of sge[1] .. sge[n]. Therefore, inline data cannot be
+ * supported if ERDMA_MAX_SGE is below 2 elements.
+ */
+#define ERDMA_MAX_INLINE	(sizeof(struct erdma_sge) * (ERDMA_MAX_SEND_SGE))
+
+enum erdma_wc_status {
+	ERDMA_WC_SUCCESS = 0,
+	ERDMA_WC_GENERAL_ERR = 1,
+	ERDMA_WC_RECV_WQE_FORMAT_ERR = 2,
+	ERDMA_WC_RECV_STAG_INVALID_ERR = 3,
+	ERDMA_WC_RECV_ADDR_VIOLATION_ERR = 4,
+	ERDMA_WC_RECV_RIGHT_VIOLATION_ERR = 5,
+	ERDMA_WC_RECV_PDID_ERR = 6,
+	ERDMA_WC_RECV_WARRPING_ERR = 7,
+	ERDMA_WC_SEND_WQE_FORMAT_ERR = 8,
+	ERDMA_WC_SEND_WQE_ORD_EXCEED = 9,
+	ERDMA_WC_SEND_STAG_INVALID_ERR = 10,
+	ERDMA_WC_SEND_ADDR_VIOLATION_ERR = 11,
+	ERDMA_WC_SEND_RIGHT_VIOLATION_ERR = 12,
+	ERDMA_WC_SEND_PDID_ERR = 13,
+	ERDMA_WC_SEND_WARRPING_ERR = 14,
+	ERDMA_WC_FLUSH_ERR = 15,
+	ERDMA_WC_RETRY_EXC_ERR = 16,
+	ERDMA_NUM_WC_STATUS
+};
+
+enum erdma_vendor_err {
+	ERDMA_WC_VENDOR_NO_ERR = 0,
+	ERDMA_WC_VENDOR_INVALID_RQE = 1,
+	ERDMA_WC_VENDOR_RQE_INVALID_STAG = 2,
+	ERDMA_WC_VENDOR_RQE_ADDR_VIOLATION = 3,
+	ERDMA_WC_VENDOR_RQE_ACCESS_RIGHT_ERR = 4,
+	ERDMA_WC_VENDOR_RQE_INVALID_PD = 5,
+	ERDMA_WC_VENDOR_RQE_WRAP_ERR = 6,
+	ERDMA_WC_VENDOR_INVALID_SQE = 0x20,
+	ERDMA_WC_VENDOR_ZERO_ORD = 0x21,
+	ERDMA_WC_VENDOR_SQE_INVALID_STAG = 0x30,
+	ERDMA_WC_VENDOR_SQE_ADDR_VIOLATION = 0x31,
+	ERDMA_WC_VENDOR_SQE_ACCESS_ERR = 0x32,
+	ERDMA_WC_VENDOR_SQE_INVALID_PD = 0x33,
+	ERDMA_WC_VENDOR_SQE_WARP_ERR = 0x34
+};
+
+
+/* Doorbell related. */
+#define ERDMA_CQDB_EQN_MASK              GENMASK_ULL(63, 56)
+#define ERDMA_CQDB_CQN_MASK              GENMASK_ULL(55, 32)
+#define ERDMA_CQDB_ARM_MASK              BIT_ULL(31)
+#define ERDMA_CQDB_SOL_MASK              BIT_ULL(30)
+#define ERDMA_CQDB_CMDSN_MASK            GENMASK_ULL(29, 28)
+#define ERDMA_CQDB_CI_MASK               GENMASK_ULL(23, 0)
+
+#define ERDMA_CQE_QTYPE_SQ    0
+#define ERDMA_CQE_QTYPE_RQ    1
+#define ERDMA_CQE_QTYPE_CMDQ  2
+
+/* CQE hdr */
+#define ERDMA_CQE_HDR_OWNER_MASK         BIT(31)
+#define ERDMA_CQE_HDR_OPCODE_MASK        GENMASK(23, 16)
+#define ERDMA_CQE_HDR_QTYPE_MASK         GENMASK(15, 8)
+#define ERDMA_CQE_HDR_SYNDROME_MASK      GENMASK(7, 0)
+
+#define ERDMA_CQE_QTYPE_SQ    0
+#define ERDMA_CQE_QTYPE_RQ    1
+#define ERDMA_CQE_QTYPE_CMDQ  2
+
+
+struct erdma_cqe {
+	__be32 hdr;
+	__be32 qe_idx;
+	__be32 qpn;
+	__le32 imm_data;
+	__be32 size;
+	__be32 rsvd[3];
+};
+
+struct erdma_sge {
+	__aligned_le64 laddr;
+	__le32 length;
+	__le32 lkey;
+};
+
+/* Receive Queue Element */
+struct erdma_rqe {
+	__le16 qe_idx;
+	__le16 rsvd;
+	__le32 qpn;
+	__le32 rsvd2;
+	__le32 rsvd3;
+	__le64 to;
+	__le32 length;
+	__le32 stag;
+};
+
+/* SQE */
+#define ERDMA_SQE_HDR_SGL_LEN_MASK       GENMASK_ULL(63, 56)
+#define ERDMA_SQE_HDR_WQEBB_CNT_MASK     GENMASK_ULL(54, 52)
+#define ERDMA_SQE_HDR_QPN_MASK           GENMASK_ULL(51, 32)
+#define ERDMA_SQE_HDR_OPCODE_MASK        GENMASK_ULL(31, 27)
+#define ERDMA_SQE_HDR_DWQE_MASK          BIT_ULL(26)
+#define ERDMA_SQE_HDR_INLINE_MASK        BIT_ULL(25)
+#define ERDMA_SQE_HDR_FENCE_MASK         BIT_ULL(24)
+#define ERDMA_SQE_HDR_SE_MASK            BIT_ULL(23)
+#define ERDMA_SQE_HDR_CE_MASK            BIT_ULL(22)
+#define ERDMA_SQE_HDR_WQEBB_INDEX_MASK   GENMASK_ULL(15, 0)
+
+struct erdma_write_sqe {
+	__le64 hdr;
+	__be32 imm_data;
+	__le32 length;
+
+	__le32 sink_stag;
+	/* avoid sink_to not 8-byte aligned. */
+	__le32 sink_to_low;
+	__le32 sink_to_high;
+
+	__le32 rsvd;
+
+	struct erdma_sge sgl[0];
+};
+
+struct erdma_send_sqe {
+	__le64 hdr;
+	__be32 imm_data;
+	__le32 length;
+	struct erdma_sge sgl[0];
+};
+
+struct erdma_readreq_sqe {
+	__le64 hdr;
+	__le32 invalid_stag;
+	__le32 length;
+	__le32 sink_stag;
+	/* avoid sink_to not 8-byte aligned. */
+	__le32 sink_to_low;
+	__le32 sink_to_high;
+	__le32 rsvd0;
+	struct erdma_sge sgl;
+};
+
+
+#endif
diff --git a/providers/erdma/erdma_verbs.h b/providers/erdma/erdma_verbs.h
new file mode 100644
index 00000000..944d29f5
--- /dev/null
+++ b/providers/erdma/erdma_verbs.h
@@ -0,0 +1,134 @@ 
+/* SPDX-License-Identifier: GPL-2.0 or OpenIB.org BSD (MIT) See COPYING file */
+/*
+ * Authors: Cheng Xu <chengyou@linux.alibaba.com>
+ * Copyright (c) 2020-2021, Alibaba Group.
+ */
+
+#ifndef __ERDMA_VERBS_H__
+#define __ERDMA_VERBS_H__
+
+#include <pthread.h>
+#include <inttypes.h>
+#include <stddef.h>
+
+#include "erdma.h"
+#include "erdma_hw.h"
+
+#define ERDMA_MAX_SEND_SGE 6
+#define ERDMA_MAX_RECV_SGE 1
+
+struct erdma_queue {
+	void *qbuf;
+	void *db;
+
+	uint16_t rsvd0;
+	uint16_t depth;
+	uint32_t size;
+
+	uint16_t pi;
+	uint16_t ci;
+
+	uint32_t rsvd1;
+	uint64_t *wr_tbl;
+
+	void *db_record;
+};
+
+struct erdma_qp {
+	struct ibv_qp base_qp;
+	struct erdma_device *erdma_dev;
+
+	uint32_t id;  /* qpn */
+
+	pthread_spinlock_t sq_lock;
+	pthread_spinlock_t rq_lock;
+
+	int sq_sig_all;
+
+	struct erdma_queue sq;
+	struct erdma_queue rq;
+
+	void *qbuf;
+	uint64_t *db_records;
+};
+
+struct erdma_cq {
+	struct ibv_cq base_cq;
+	struct erdma_device *erdma_dev;
+	uint32_t id;
+
+	uint32_t event_stats;
+
+	uint32_t depth;
+	uint32_t ci;
+	uint32_t owner;
+	struct erdma_cqe *queue;
+
+	void *db;
+	uint16_t db_offset;
+
+	void *db_record;
+	uint32_t cmdsn;
+	int comp_vector;
+
+	pthread_spinlock_t lock;
+};
+
+static inline struct erdma_qp *to_eqp(struct ibv_qp *base)
+{
+	return container_of(base, struct erdma_qp, base_qp);
+}
+
+static inline struct erdma_cq *to_ecq(struct ibv_cq *base)
+{
+	return container_of(base, struct erdma_cq, base_cq);
+}
+
+static inline void *get_sq_wqebb(struct erdma_qp *qp, uint16_t idx)
+{
+	idx &= (qp->sq.depth - 1);
+	return qp->sq.qbuf + (idx << SQEBB_SHIFT);
+}
+
+static inline void __kick_sq_db(struct erdma_qp *qp, uint16_t pi)
+{
+	uint64_t db_data;
+
+	db_data = FIELD_PREP(ERDMA_SQE_HDR_QPN_MASK, qp->id) |
+		FIELD_PREP(ERDMA_SQE_HDR_WQEBB_INDEX_MASK, pi);
+
+	*(__le64 *)qp->sq.db_record = htole64(db_data);
+	udma_to_device_barrier();
+	mmio_write64_le(qp->sq.db, htole64(db_data));
+}
+
+struct ibv_pd *erdma_alloc_pd(struct ibv_context *ctx);
+int erdma_free_pd(struct ibv_pd *pd);
+
+int erdma_query_device(struct ibv_context *ctx,
+		       const struct ibv_query_device_ex_input *input,
+		       struct ibv_device_attr_ex *attr, size_t attr_size);
+int erdma_query_port(struct ibv_context *ctx, uint8_t port, struct ibv_port_attr *attr);
+
+struct ibv_mr *erdma_reg_mr(struct ibv_pd *pd, void *addr, size_t len,
+			    uint64_t hca_va, int access);
+int erdma_dereg_mr(struct verbs_mr *vmr);
+
+struct ibv_qp *erdma_create_qp(struct ibv_pd *pd, struct ibv_qp_init_attr *attr);
+int erdma_modify_qp(struct ibv_qp *base_qp, struct ibv_qp_attr *attr, int attr_mask);
+int erdma_query_qp(struct ibv_qp *qp, struct ibv_qp_attr *attr,
+		   int attr_mask, struct ibv_qp_init_attr *init_attr);
+int erdma_post_send(struct ibv_qp *base_qp, struct ibv_send_wr *wr, struct ibv_send_wr **bad_wr);
+int erdma_post_recv(struct ibv_qp *base_qp, struct ibv_recv_wr *wr, struct ibv_recv_wr **bad_wr);
+int erdma_destroy_qp(struct ibv_qp *base_qp);
+
+void erdma_free_context(struct ibv_context *ibv_ctx);
+
+struct ibv_cq *erdma_create_cq(struct ibv_context *ctx, int num_cqe,
+			       struct ibv_comp_channel *channel, int comp_vector);
+int erdma_destroy_cq(struct ibv_cq *base_cq);
+int erdma_notify_cq(struct ibv_cq *ibcq, int solicited);
+void erdma_cq_event(struct ibv_cq *ibcq);
+int erdma_poll_cq(struct ibv_cq *ibcq, int num_entries, struct ibv_wc *wc);
+
+#endif