public inbox for linux-rdma@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH for-next 0/8] RDMA/erdma: Support the RoCEv2 protocol
@ 2024-11-26  6:59 Boshi Yu
  2024-11-26  6:59 ` [PATCH for-next 1/8] RDMA/erdma: Probe the erdma RoCEv2 device Boshi Yu
                   ` (7 more replies)
  0 siblings, 8 replies; 21+ messages in thread
From: Boshi Yu @ 2024-11-26  6:59 UTC (permalink / raw)
  To: jgg, leon; +Cc: linux-rdma, kaishen, chengyou

Hi,

This patch series introduces support for the RoCEv2 protocol into the
erdma driver. As the most prevalent RDMA protocol, RoCEv2 is widely
used in the production environment. Given the extensive application of
erdma across various scenarios in the Alibaba Cloud, there has arisen a
requirement for erdma to support the RoCEv2 protocol. Therefore, we update
both the erdma hardware and the erdma driver to accommodate the RoCEv2
protocol.

- #1 adds the device probe logic for the erdma RoCEv2 device.
- #2~#4 implement resource management interfaces required by the erdma
  RoCEv2 device, such as the GID table, PKey and address handle.
- #5~#6 implment the modify QP interface for the erdma RoCEv2 device and
  reformat the code of modify_qp interface to improve readability.
- #7 introduces the query_qp command to obtain several qp attributes
  from the hardware.
- #8 extends the procedure for create_qp, post_send and poll_cq interfaces
  to support UD QPs and UD WRs.

Thanks,
Boshi Yu

Boshi Yu (8):
  RDMA/erdma: Probe the erdma RoCEv2 device
  RDMA/erdma: Add GID table management interfaces
  RDMA/erdma: Add the erdma_query_pkey() interface
  RDMA/erdma: Add address handle implementation
  RDMA/erdma: Add erdma_modify_qp_rocev2() interface
  RDMA/erdma: Reformat the code of the modify_qp interface
  RDMA/erdma: Add the query_qp command to the cmdq
  RDMA/erdma: Support UD QPs and UD WRs

 drivers/infiniband/hw/erdma/Kconfig       |   2 +-
 drivers/infiniband/hw/erdma/erdma.h       |   8 +-
 drivers/infiniband/hw/erdma/erdma_cm.c    |  71 +--
 drivers/infiniband/hw/erdma/erdma_cq.c    |  65 +++
 drivers/infiniband/hw/erdma/erdma_hw.h    | 135 +++++-
 drivers/infiniband/hw/erdma/erdma_main.c  |  57 ++-
 drivers/infiniband/hw/erdma/erdma_qp.c    | 299 +++++++++---
 drivers/infiniband/hw/erdma/erdma_verbs.c | 524 +++++++++++++++++++---
 drivers/infiniband/hw/erdma/erdma_verbs.h | 171 +++++--
 9 files changed, 1134 insertions(+), 198 deletions(-)

-- 
2.43.5


^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH for-next 1/8] RDMA/erdma: Probe the erdma RoCEv2 device
  2024-11-26  6:59 [PATCH for-next 0/8] RDMA/erdma: Support the RoCEv2 protocol Boshi Yu
@ 2024-11-26  6:59 ` Boshi Yu
  2024-11-26 15:36   ` Zhu Yanjun
  2024-12-04 14:03   ` Leon Romanovsky
  2024-11-26  6:59 ` [PATCH for-next 2/8] RDMA/erdma: Add GID table management interfaces Boshi Yu
                   ` (6 subsequent siblings)
  7 siblings, 2 replies; 21+ messages in thread
From: Boshi Yu @ 2024-11-26  6:59 UTC (permalink / raw)
  To: jgg, leon; +Cc: linux-rdma, kaishen, chengyou

Currently, the erdma driver supports both the iWARP and RoCEv2 protocols.
The erdma driver reads the ERDMA_REGS_DEV_PROTO_REG register to identify
the protocol used by the erdma device. Since each protocol requires
different ib_device_ops, we introduce the erdma_device_ops_iwarp and
erdma_device_ops_rocev2 for iWARP and RoCEv2 protocols, respectively.

Signed-off-by: Boshi Yu <boshiyu@linux.alibaba.com>
Reviewed-by: Cheng Xu <chengyou@linux.alibaba.com>
---
 drivers/infiniband/hw/erdma/Kconfig       |  2 +-
 drivers/infiniband/hw/erdma/erdma.h       |  3 +-
 drivers/infiniband/hw/erdma/erdma_hw.h    |  7 ++++
 drivers/infiniband/hw/erdma/erdma_main.c  | 47 ++++++++++++++++++-----
 drivers/infiniband/hw/erdma/erdma_verbs.c | 16 +++++++-
 drivers/infiniband/hw/erdma/erdma_verbs.h | 12 ++++++
 6 files changed, 75 insertions(+), 12 deletions(-)

diff --git a/drivers/infiniband/hw/erdma/Kconfig b/drivers/infiniband/hw/erdma/Kconfig
index 169038e3ceb1..267fc1f3c42a 100644
--- a/drivers/infiniband/hw/erdma/Kconfig
+++ b/drivers/infiniband/hw/erdma/Kconfig
@@ -5,7 +5,7 @@ config INFINIBAND_ERDMA
 	depends on INFINIBAND_ADDR_TRANS
 	depends on INFINIBAND_USER_ACCESS
 	help
-	  This is a RDMA/iWarp driver for Alibaba Elastic RDMA Adapter(ERDMA),
+	  This is a RDMA driver for Alibaba Elastic RDMA Adapter(ERDMA),
 	  which supports RDMA features in Alibaba cloud environment.
 
 	  To compile this driver as module, choose M here. The module will be
diff --git a/drivers/infiniband/hw/erdma/erdma.h b/drivers/infiniband/hw/erdma/erdma.h
index 3c166359448d..ad4dc1a4bdc7 100644
--- a/drivers/infiniband/hw/erdma/erdma.h
+++ b/drivers/infiniband/hw/erdma/erdma.h
@@ -16,7 +16,7 @@
 #include "erdma_hw.h"
 
 #define DRV_MODULE_NAME "erdma"
-#define ERDMA_NODE_DESC "Elastic RDMA(iWARP) stack"
+#define ERDMA_NODE_DESC "Elastic RDMA Adapter stack"
 
 struct erdma_eq {
 	void *qbuf;
@@ -215,6 +215,7 @@ struct erdma_dev {
 
 	struct dma_pool *db_pool;
 	struct dma_pool *resp_pool;
+	enum erdma_proto_type proto;
 };
 
 static inline void *get_queue_entry(void *qbuf, u32 idx, u32 depth, u32 shift)
diff --git a/drivers/infiniband/hw/erdma/erdma_hw.h b/drivers/infiniband/hw/erdma/erdma_hw.h
index 05978f3b1475..970b392d4fb4 100644
--- a/drivers/infiniband/hw/erdma/erdma_hw.h
+++ b/drivers/infiniband/hw/erdma/erdma_hw.h
@@ -21,8 +21,15 @@
 #define ERDMA_NUM_MSIX_VEC 32U
 #define ERDMA_MSIX_VECTOR_CMDQ 0
 
+/* erdma device protocol type */
+enum erdma_proto_type {
+	ERDMA_PROTO_IWARP = 0,
+	ERDMA_PROTO_ROCEV2 = 1,
+};
+
 /* PCIe Bar0 Registers. */
 #define ERDMA_REGS_VERSION_REG 0x0
+#define ERDMA_REGS_DEV_PROTO_REG 0xC
 #define ERDMA_REGS_DEV_CTRL_REG 0x10
 #define ERDMA_REGS_DEV_ST_REG 0x14
 #define ERDMA_REGS_NETDEV_MAC_L_REG 0x18
diff --git a/drivers/infiniband/hw/erdma/erdma_main.c b/drivers/infiniband/hw/erdma/erdma_main.c
index 62f497a71004..b6706c74cd96 100644
--- a/drivers/infiniband/hw/erdma/erdma_main.c
+++ b/drivers/infiniband/hw/erdma/erdma_main.c
@@ -172,6 +172,12 @@ static int erdma_device_init(struct erdma_dev *dev, struct pci_dev *pdev)
 {
 	int ret;
 
+	dev->proto = erdma_reg_read32(dev, ERDMA_REGS_DEV_PROTO_REG);
+	if (!erdma_device_iwarp(dev) && !erdma_device_rocev2(dev)) {
+		dev_err(&pdev->dev, "Unsupported protocol: %d\n", dev->proto);
+		return -ENODEV;
+	}
+
 	dev->resp_pool = dma_pool_create("erdma_resp_pool", &pdev->dev,
 					 ERDMA_HW_RESP_SIZE, ERDMA_HW_RESP_SIZE,
 					 0);
@@ -474,6 +480,21 @@ static void erdma_res_cb_free(struct erdma_dev *dev)
 		bitmap_free(dev->res_cb[i].bitmap);
 }
 
+static const struct ib_device_ops erdma_device_ops_rocev2 = {
+	.get_link_layer = erdma_get_link_layer,
+};
+
+static const struct ib_device_ops erdma_device_ops_iwarp = {
+	.iw_accept = erdma_accept,
+	.iw_add_ref = erdma_qp_get_ref,
+	.iw_connect = erdma_connect,
+	.iw_create_listen = erdma_create_listen,
+	.iw_destroy_listen = erdma_destroy_listen,
+	.iw_get_qp = erdma_get_ibqp,
+	.iw_reject = erdma_reject,
+	.iw_rem_ref = erdma_qp_put_ref,
+};
+
 static const struct ib_device_ops erdma_device_ops = {
 	.owner = THIS_MODULE,
 	.driver_id = RDMA_DRIVER_ERDMA,
@@ -494,14 +515,6 @@ static const struct ib_device_ops erdma_device_ops = {
 	.get_dma_mr = erdma_get_dma_mr,
 	.get_hw_stats = erdma_get_hw_stats,
 	.get_port_immutable = erdma_get_port_immutable,
-	.iw_accept = erdma_accept,
-	.iw_add_ref = erdma_qp_get_ref,
-	.iw_connect = erdma_connect,
-	.iw_create_listen = erdma_create_listen,
-	.iw_destroy_listen = erdma_destroy_listen,
-	.iw_get_qp = erdma_get_ibqp,
-	.iw_reject = erdma_reject,
-	.iw_rem_ref = erdma_qp_put_ref,
 	.map_mr_sg = erdma_map_mr_sg,
 	.mmap = erdma_mmap,
 	.mmap_free = erdma_mmap_free,
@@ -522,6 +535,18 @@ static const struct ib_device_ops erdma_device_ops = {
 	INIT_RDMA_OBJ_SIZE(ib_qp, erdma_qp, ibqp),
 };
 
+static void erdma_device_init_iwarp(struct ib_device *ibdev)
+{
+	ibdev->node_type = RDMA_NODE_RNIC;
+	ib_set_device_ops(ibdev, &erdma_device_ops_iwarp);
+}
+
+static void erdma_device_init_rocev2(struct ib_device *ibdev)
+{
+	ibdev->node_type = RDMA_NODE_IB_CA;
+	ib_set_device_ops(ibdev, &erdma_device_ops_rocev2);
+}
+
 static int erdma_ib_device_add(struct pci_dev *pdev)
 {
 	struct erdma_dev *dev = pci_get_drvdata(pdev);
@@ -537,7 +562,11 @@ static int erdma_ib_device_add(struct pci_dev *pdev)
 	if (ret)
 		return ret;
 
-	ibdev->node_type = RDMA_NODE_RNIC;
+	if (erdma_device_iwarp(dev))
+		erdma_device_init_iwarp(&dev->ibdev);
+	else
+		erdma_device_init_rocev2(&dev->ibdev);
+
 	memcpy(ibdev->node_desc, ERDMA_NODE_DESC, sizeof(ERDMA_NODE_DESC));
 
 	/*
diff --git a/drivers/infiniband/hw/erdma/erdma_verbs.c b/drivers/infiniband/hw/erdma/erdma_verbs.c
index 51d619edb6c5..3b7e55515cfd 100644
--- a/drivers/infiniband/hw/erdma/erdma_verbs.c
+++ b/drivers/infiniband/hw/erdma/erdma_verbs.c
@@ -395,8 +395,17 @@ int erdma_query_port(struct ib_device *ibdev, u32 port,
 int erdma_get_port_immutable(struct ib_device *ibdev, u32 port,
 			     struct ib_port_immutable *port_immutable)
 {
+	struct erdma_dev *dev = to_edev(ibdev);
+
+	if (erdma_device_iwarp(dev)) {
+		port_immutable->core_cap_flags = RDMA_CORE_PORT_IWARP;
+	} else {
+		port_immutable->core_cap_flags =
+			RDMA_CORE_PORT_IBA_ROCE_UDP_ENCAP;
+		port_immutable->max_mad_size = IB_MGMT_MAD_SIZE;
+	}
+
 	port_immutable->gid_tbl_len = 1;
-	port_immutable->core_cap_flags = RDMA_CORE_PORT_IWARP;
 
 	return 0;
 }
@@ -1839,3 +1848,8 @@ int erdma_get_hw_stats(struct ib_device *ibdev, struct rdma_hw_stats *stats,
 
 	return stats->num_counters;
 }
+
+enum rdma_link_layer erdma_get_link_layer(struct ib_device *ibdev, u32 port_num)
+{
+	return IB_LINK_LAYER_ETHERNET;
+}
diff --git a/drivers/infiniband/hw/erdma/erdma_verbs.h b/drivers/infiniband/hw/erdma/erdma_verbs.h
index c998acd39a78..90e2b35a0973 100644
--- a/drivers/infiniband/hw/erdma/erdma_verbs.h
+++ b/drivers/infiniband/hw/erdma/erdma_verbs.h
@@ -291,6 +291,16 @@ int erdma_modify_qp_internal(struct erdma_qp *qp, struct erdma_qp_attrs *attrs,
 void erdma_qp_llp_close(struct erdma_qp *qp);
 void erdma_qp_cm_drop(struct erdma_qp *qp);
 
+static inline bool erdma_device_iwarp(struct erdma_dev *dev)
+{
+	return dev->proto == ERDMA_PROTO_IWARP;
+}
+
+static inline bool erdma_device_rocev2(struct erdma_dev *dev)
+{
+	return dev->proto == ERDMA_PROTO_ROCEV2;
+}
+
 static inline struct erdma_ucontext *to_ectx(struct ib_ucontext *ibctx)
 {
 	return container_of(ibctx, struct erdma_ucontext, ibucontext);
@@ -370,5 +380,7 @@ struct rdma_hw_stats *erdma_alloc_hw_port_stats(struct ib_device *device,
 						u32 port_num);
 int erdma_get_hw_stats(struct ib_device *ibdev, struct rdma_hw_stats *stats,
 		       u32 port, int index);
+enum rdma_link_layer erdma_get_link_layer(struct ib_device *ibdev,
+					  u32 port_num);
 
 #endif
-- 
2.43.5


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH for-next 2/8] RDMA/erdma: Add GID table management interfaces
  2024-11-26  6:59 [PATCH for-next 0/8] RDMA/erdma: Support the RoCEv2 protocol Boshi Yu
  2024-11-26  6:59 ` [PATCH for-next 1/8] RDMA/erdma: Probe the erdma RoCEv2 device Boshi Yu
@ 2024-11-26  6:59 ` Boshi Yu
  2024-11-26 15:51   ` Zhu Yanjun
  2024-11-26  6:59 ` [PATCH for-next 3/8] RDMA/erdma: Add the erdma_query_pkey() interface Boshi Yu
                   ` (5 subsequent siblings)
  7 siblings, 1 reply; 21+ messages in thread
From: Boshi Yu @ 2024-11-26  6:59 UTC (permalink / raw)
  To: jgg, leon; +Cc: linux-rdma, kaishen, chengyou

The erdma_add_gid() interface inserts a GID entry at the
specified index. The erdma_del_gid() interface deletes the
GID entry at the specified index. Additionally, programs
can invoke the erdma_query_port() and erdma_get_port_immutable()
interfaces to query the GID table length.

Signed-off-by: Boshi Yu <boshiyu@linux.alibaba.com>
Reviewed-by: Cheng Xu <chengyou@linux.alibaba.com>
---
 drivers/infiniband/hw/erdma/erdma.h       |  1 +
 drivers/infiniband/hw/erdma/erdma_hw.h    | 28 +++++++++++-
 drivers/infiniband/hw/erdma/erdma_main.c  |  3 ++
 drivers/infiniband/hw/erdma/erdma_verbs.c | 56 +++++++++++++++++++++--
 drivers/infiniband/hw/erdma/erdma_verbs.h | 12 +++++
 5 files changed, 96 insertions(+), 4 deletions(-)

diff --git a/drivers/infiniband/hw/erdma/erdma.h b/drivers/infiniband/hw/erdma/erdma.h
index ad4dc1a4bdc7..42dabf674f5d 100644
--- a/drivers/infiniband/hw/erdma/erdma.h
+++ b/drivers/infiniband/hw/erdma/erdma.h
@@ -148,6 +148,7 @@ struct erdma_devattr {
 	u32 max_mr;
 	u32 max_pd;
 	u32 max_mw;
+	u32 max_gid;
 	u32 local_dma_key;
 };
 
diff --git a/drivers/infiniband/hw/erdma/erdma_hw.h b/drivers/infiniband/hw/erdma/erdma_hw.h
index 970b392d4fb4..7e03c5f97501 100644
--- a/drivers/infiniband/hw/erdma/erdma_hw.h
+++ b/drivers/infiniband/hw/erdma/erdma_hw.h
@@ -21,6 +21,9 @@
 #define ERDMA_NUM_MSIX_VEC 32U
 #define ERDMA_MSIX_VECTOR_CMDQ 0
 
+/* RoCEv2 related */
+#define ERDMA_ROCEV2_GID_SIZE 16
+
 /* erdma device protocol type */
 enum erdma_proto_type {
 	ERDMA_PROTO_IWARP = 0,
@@ -143,7 +146,8 @@ enum CMDQ_RDMA_OPCODE {
 	CMDQ_OPCODE_DESTROY_CQ = 5,
 	CMDQ_OPCODE_REFLUSH = 6,
 	CMDQ_OPCODE_REG_MR = 8,
-	CMDQ_OPCODE_DEREG_MR = 9
+	CMDQ_OPCODE_DEREG_MR = 9,
+	CMDQ_OPCODE_SET_GID = 14,
 };
 
 enum CMDQ_COMMON_OPCODE {
@@ -401,7 +405,29 @@ struct erdma_cmdq_query_stats_resp {
 	u64 rx_pps_meter_drop_packets_cnt;
 };
 
+enum erdma_network_type {
+	ERDMA_NETWORK_TYPE_IPV4 = 0,
+	ERDMA_NETWORK_TYPE_IPV6 = 1,
+};
+
+enum erdma_set_gid_op {
+	ERDMA_SET_GID_OP_ADD = 0,
+	ERDMA_SET_GID_OP_DEL = 1,
+};
+
+/* set gid cfg */
+#define ERDMA_CMD_SET_GID_SGID_IDX_MASK GENMASK(15, 0)
+#define ERDMA_CMD_SET_GID_NTYPE_MASK BIT(16)
+#define ERDMA_CMD_SET_GID_OP_MASK BIT(31)
+
+struct erdma_cmdq_set_gid_req {
+	u64 hdr;
+	u32 cfg;
+	u8 gid[ERDMA_ROCEV2_GID_SIZE];
+};
+
 /* cap qword 0 definition */
+#define ERDMA_CMD_DEV_CAP_MAX_GID_MASK GENMASK_ULL(51, 48)
 #define ERDMA_CMD_DEV_CAP_MAX_CQE_MASK GENMASK_ULL(47, 40)
 #define ERDMA_CMD_DEV_CAP_FLAGS_MASK GENMASK_ULL(31, 24)
 #define ERDMA_CMD_DEV_CAP_MAX_RECV_WR_MASK GENMASK_ULL(23, 16)
diff --git a/drivers/infiniband/hw/erdma/erdma_main.c b/drivers/infiniband/hw/erdma/erdma_main.c
index b6706c74cd96..d72b85e8971d 100644
--- a/drivers/infiniband/hw/erdma/erdma_main.c
+++ b/drivers/infiniband/hw/erdma/erdma_main.c
@@ -404,6 +404,7 @@ static int erdma_dev_attrs_init(struct erdma_dev *dev)
 	dev->attrs.max_mr_size = 1ULL << ERDMA_GET_CAP(MAX_MR_SIZE, cap0);
 	dev->attrs.max_mw = 1 << ERDMA_GET_CAP(MAX_MW, cap1);
 	dev->attrs.max_recv_wr = 1 << ERDMA_GET_CAP(MAX_RECV_WR, cap0);
+	dev->attrs.max_gid = 1 << ERDMA_GET_CAP(MAX_GID, cap0);
 	dev->attrs.local_dma_key = ERDMA_GET_CAP(DMA_LOCAL_KEY, cap1);
 	dev->attrs.cc = ERDMA_GET_CAP(DEFAULT_CC, cap1);
 	dev->attrs.max_qp = ERDMA_NQP_PER_QBLOCK * ERDMA_GET_CAP(QBLOCK, cap1);
@@ -482,6 +483,8 @@ static void erdma_res_cb_free(struct erdma_dev *dev)
 
 static const struct ib_device_ops erdma_device_ops_rocev2 = {
 	.get_link_layer = erdma_get_link_layer,
+	.add_gid = erdma_add_gid,
+	.del_gid = erdma_del_gid,
 };
 
 static const struct ib_device_ops erdma_device_ops_iwarp = {
diff --git a/drivers/infiniband/hw/erdma/erdma_verbs.c b/drivers/infiniband/hw/erdma/erdma_verbs.c
index 3b7e55515cfd..9944eed584ec 100644
--- a/drivers/infiniband/hw/erdma/erdma_verbs.c
+++ b/drivers/infiniband/hw/erdma/erdma_verbs.c
@@ -367,7 +367,13 @@ int erdma_query_port(struct ib_device *ibdev, u32 port,
 
 	memset(attr, 0, sizeof(*attr));
 
-	attr->gid_tbl_len = 1;
+	if (erdma_device_iwarp(dev)) {
+		attr->gid_tbl_len = 1;
+	} else {
+		attr->gid_tbl_len = dev->attrs.max_gid;
+		attr->ip_gids = true;
+	}
+
 	attr->port_cap_flags = IB_PORT_CM_SUP | IB_PORT_DEVICE_MGMT_SUP;
 	attr->max_msg_sz = -1;
 
@@ -399,14 +405,14 @@ int erdma_get_port_immutable(struct ib_device *ibdev, u32 port,
 
 	if (erdma_device_iwarp(dev)) {
 		port_immutable->core_cap_flags = RDMA_CORE_PORT_IWARP;
+		port_immutable->gid_tbl_len = 1;
 	} else {
 		port_immutable->core_cap_flags =
 			RDMA_CORE_PORT_IBA_ROCE_UDP_ENCAP;
 		port_immutable->max_mad_size = IB_MGMT_MAD_SIZE;
+		port_immutable->gid_tbl_len = dev->attrs.max_gid;
 	}
 
-	port_immutable->gid_tbl_len = 1;
-
 	return 0;
 }
 
@@ -1853,3 +1859,47 @@ enum rdma_link_layer erdma_get_link_layer(struct ib_device *ibdev, u32 port_num)
 {
 	return IB_LINK_LAYER_ETHERNET;
 }
+
+static int erdma_set_gid(struct erdma_dev *dev, u8 op, u32 idx,
+			 const union ib_gid *gid)
+{
+	struct erdma_cmdq_set_gid_req req;
+	u8 ntype;
+
+	req.cfg = FIELD_PREP(ERDMA_CMD_SET_GID_SGID_IDX_MASK, idx) |
+		  FIELD_PREP(ERDMA_CMD_SET_GID_OP_MASK, op);
+
+	if (op == ERDMA_SET_GID_OP_ADD) {
+		if (ipv6_addr_v4mapped((struct in6_addr *)gid))
+			ntype = ERDMA_NETWORK_TYPE_IPV4;
+		else
+			ntype = ERDMA_NETWORK_TYPE_IPV6;
+
+		req.cfg |= FIELD_PREP(ERDMA_CMD_SET_GID_NTYPE_MASK, ntype);
+
+		memcpy(&req.gid, gid, ERDMA_ROCEV2_GID_SIZE);
+	}
+
+	erdma_cmdq_build_reqhdr(&req.hdr, CMDQ_SUBMOD_RDMA,
+				CMDQ_OPCODE_SET_GID);
+	return erdma_post_cmd_wait(&dev->cmdq, &req, sizeof(req), NULL, NULL);
+}
+
+int erdma_add_gid(const struct ib_gid_attr *attr, void **context)
+{
+	struct erdma_dev *dev = to_edev(attr->device);
+	int ret;
+
+	ret = erdma_check_gid_attr(attr);
+	if (ret)
+		return ret;
+
+	return erdma_set_gid(dev, ERDMA_SET_GID_OP_ADD, attr->index,
+			     &attr->gid);
+}
+
+int erdma_del_gid(const struct ib_gid_attr *attr, void **context)
+{
+	return erdma_set_gid(to_edev(attr->device), ERDMA_SET_GID_OP_DEL,
+			     attr->index, NULL);
+}
diff --git a/drivers/infiniband/hw/erdma/erdma_verbs.h b/drivers/infiniband/hw/erdma/erdma_verbs.h
index 90e2b35a0973..23cfeaf79eaa 100644
--- a/drivers/infiniband/hw/erdma/erdma_verbs.h
+++ b/drivers/infiniband/hw/erdma/erdma_verbs.h
@@ -326,6 +326,16 @@ static inline struct erdma_cq *to_ecq(struct ib_cq *ibcq)
 	return container_of(ibcq, struct erdma_cq, ibcq);
 }
 
+static inline int erdma_check_gid_attr(const struct ib_gid_attr *attr)
+{
+	u8 ntype = rdma_gid_attr_network_type(attr);
+
+	if (ntype != RDMA_NETWORK_IPV4 && ntype != RDMA_NETWORK_IPV6)
+		return -EINVAL;
+
+	return 0;
+}
+
 static inline struct erdma_user_mmap_entry *
 to_emmap(struct rdma_user_mmap_entry *ibmmap)
 {
@@ -382,5 +392,7 @@ int erdma_get_hw_stats(struct ib_device *ibdev, struct rdma_hw_stats *stats,
 		       u32 port, int index);
 enum rdma_link_layer erdma_get_link_layer(struct ib_device *ibdev,
 					  u32 port_num);
+int erdma_add_gid(const struct ib_gid_attr *attr, void **context);
+int erdma_del_gid(const struct ib_gid_attr *attr, void **context);
 
 #endif
-- 
2.43.5


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH for-next 3/8] RDMA/erdma: Add the erdma_query_pkey() interface
  2024-11-26  6:59 [PATCH for-next 0/8] RDMA/erdma: Support the RoCEv2 protocol Boshi Yu
  2024-11-26  6:59 ` [PATCH for-next 1/8] RDMA/erdma: Probe the erdma RoCEv2 device Boshi Yu
  2024-11-26  6:59 ` [PATCH for-next 2/8] RDMA/erdma: Add GID table management interfaces Boshi Yu
@ 2024-11-26  6:59 ` Boshi Yu
  2024-11-26  6:59 ` [PATCH for-next 4/8] RDMA/erdma: Add address handle implementation Boshi Yu
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 21+ messages in thread
From: Boshi Yu @ 2024-11-26  6:59 UTC (permalink / raw)
  To: jgg, leon; +Cc: linux-rdma, kaishen, chengyou

The erdma_query_pkey() interface queries the PKey at the specified
index. Currently, erdma supports only one partition and returns the
default PKey for each query. Besides, the correct length of the PKey
table can be obtained by calling the erdma_query_port() and
erdma_get_port_immutable() interfaces.

Signed-off-by: Boshi Yu <boshiyu@linux.alibaba.com>
Reviewed-by: Cheng Xu <chengyou@linux.alibaba.com>
---
 drivers/infiniband/hw/erdma/erdma_hw.h    |  2 ++
 drivers/infiniband/hw/erdma/erdma_main.c  |  1 +
 drivers/infiniband/hw/erdma/erdma_verbs.c | 14 ++++++++++++++
 drivers/infiniband/hw/erdma/erdma_verbs.h |  1 +
 4 files changed, 18 insertions(+)

diff --git a/drivers/infiniband/hw/erdma/erdma_hw.h b/drivers/infiniband/hw/erdma/erdma_hw.h
index 7e03c5f97501..f7f9dcac3ab0 100644
--- a/drivers/infiniband/hw/erdma/erdma_hw.h
+++ b/drivers/infiniband/hw/erdma/erdma_hw.h
@@ -23,6 +23,8 @@
 
 /* RoCEv2 related */
 #define ERDMA_ROCEV2_GID_SIZE 16
+#define ERDMA_MAX_PKEYS 1
+#define ERDMA_DEFAULT_PKEY 0xFFFF
 
 /* erdma device protocol type */
 enum erdma_proto_type {
diff --git a/drivers/infiniband/hw/erdma/erdma_main.c b/drivers/infiniband/hw/erdma/erdma_main.c
index d72b85e8971d..fca5bf7519dd 100644
--- a/drivers/infiniband/hw/erdma/erdma_main.c
+++ b/drivers/infiniband/hw/erdma/erdma_main.c
@@ -485,6 +485,7 @@ static const struct ib_device_ops erdma_device_ops_rocev2 = {
 	.get_link_layer = erdma_get_link_layer,
 	.add_gid = erdma_add_gid,
 	.del_gid = erdma_del_gid,
+	.query_pkey = erdma_query_pkey,
 };
 
 static const struct ib_device_ops erdma_device_ops_iwarp = {
diff --git a/drivers/infiniband/hw/erdma/erdma_verbs.c b/drivers/infiniband/hw/erdma/erdma_verbs.c
index 9944eed584ec..03ea52bb233e 100644
--- a/drivers/infiniband/hw/erdma/erdma_verbs.c
+++ b/drivers/infiniband/hw/erdma/erdma_verbs.c
@@ -336,6 +336,9 @@ int erdma_query_device(struct ib_device *ibdev, struct ib_device_attr *attr,
 	attr->max_fast_reg_page_list_len = ERDMA_MAX_FRMR_PA;
 	attr->page_size_cap = ERDMA_PAGE_SIZE_SUPPORT;
 
+	if (erdma_device_rocev2(dev))
+		attr->max_pkeys = ERDMA_MAX_PKEYS;
+
 	if (dev->attrs.cap_flags & ERDMA_DEV_CAP_FLAGS_ATOMIC)
 		attr->atomic_cap = IB_ATOMIC_GLOB;
 
@@ -372,6 +375,7 @@ int erdma_query_port(struct ib_device *ibdev, u32 port,
 	} else {
 		attr->gid_tbl_len = dev->attrs.max_gid;
 		attr->ip_gids = true;
+		attr->pkey_tbl_len = ERDMA_MAX_PKEYS;
 	}
 
 	attr->port_cap_flags = IB_PORT_CM_SUP | IB_PORT_DEVICE_MGMT_SUP;
@@ -411,6 +415,7 @@ int erdma_get_port_immutable(struct ib_device *ibdev, u32 port,
 			RDMA_CORE_PORT_IBA_ROCE_UDP_ENCAP;
 		port_immutable->max_mad_size = IB_MGMT_MAD_SIZE;
 		port_immutable->gid_tbl_len = dev->attrs.max_gid;
+		port_immutable->pkey_tbl_len = ERDMA_MAX_PKEYS;
 	}
 
 	return 0;
@@ -1903,3 +1908,12 @@ int erdma_del_gid(const struct ib_gid_attr *attr, void **context)
 	return erdma_set_gid(to_edev(attr->device), ERDMA_SET_GID_OP_DEL,
 			     attr->index, NULL);
 }
+
+int erdma_query_pkey(struct ib_device *ibdev, u32 port, u16 index, u16 *pkey)
+{
+	if (index >= ERDMA_MAX_PKEYS)
+		return -EINVAL;
+
+	*pkey = ERDMA_DEFAULT_PKEY;
+	return 0;
+}
diff --git a/drivers/infiniband/hw/erdma/erdma_verbs.h b/drivers/infiniband/hw/erdma/erdma_verbs.h
index 23cfeaf79eaa..1ae6ba56f597 100644
--- a/drivers/infiniband/hw/erdma/erdma_verbs.h
+++ b/drivers/infiniband/hw/erdma/erdma_verbs.h
@@ -394,5 +394,6 @@ enum rdma_link_layer erdma_get_link_layer(struct ib_device *ibdev,
 					  u32 port_num);
 int erdma_add_gid(const struct ib_gid_attr *attr, void **context);
 int erdma_del_gid(const struct ib_gid_attr *attr, void **context);
+int erdma_query_pkey(struct ib_device *ibdev, u32 port, u16 index, u16 *pkey);
 
 #endif
-- 
2.43.5


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH for-next 4/8] RDMA/erdma: Add address handle implementation
  2024-11-26  6:59 [PATCH for-next 0/8] RDMA/erdma: Support the RoCEv2 protocol Boshi Yu
                   ` (2 preceding siblings ...)
  2024-11-26  6:59 ` [PATCH for-next 3/8] RDMA/erdma: Add the erdma_query_pkey() interface Boshi Yu
@ 2024-11-26  6:59 ` Boshi Yu
  2024-12-04 14:11   ` Leon Romanovsky
  2024-11-26  6:59 ` [PATCH for-next 5/8] RDMA/erdma: Add erdma_modify_qp_rocev2() interface Boshi Yu
                   ` (3 subsequent siblings)
  7 siblings, 1 reply; 21+ messages in thread
From: Boshi Yu @ 2024-11-26  6:59 UTC (permalink / raw)
  To: jgg, leon; +Cc: linux-rdma, kaishen, chengyou

The address handle contains the necessary information to transmit
messages to a remote peer in the RoCEv2 protocol. This commit
implements the erdma_create_ah(), erdma_destroy_ah(), and
erdma_query_ah() interfaces, which are used to create, destroy,
and query an address handle, respectively.

Signed-off-by: Boshi Yu <boshiyu@linux.alibaba.com>
Reviewed-by: Cheng Xu <chengyou@linux.alibaba.com>
---
 drivers/infiniband/hw/erdma/erdma.h       |   4 +-
 drivers/infiniband/hw/erdma/erdma_hw.h    |  34 ++++++
 drivers/infiniband/hw/erdma/erdma_main.c  |   4 +
 drivers/infiniband/hw/erdma/erdma_verbs.c | 135 +++++++++++++++++++++-
 drivers/infiniband/hw/erdma/erdma_verbs.h |  28 +++++
 5 files changed, 203 insertions(+), 2 deletions(-)

diff --git a/drivers/infiniband/hw/erdma/erdma.h b/drivers/infiniband/hw/erdma/erdma.h
index 42dabf674f5d..4f840d8e3beb 100644
--- a/drivers/infiniband/hw/erdma/erdma.h
+++ b/drivers/infiniband/hw/erdma/erdma.h
@@ -149,6 +149,7 @@ struct erdma_devattr {
 	u32 max_pd;
 	u32 max_mw;
 	u32 max_gid;
+	u32 max_ah;
 	u32 local_dma_key;
 };
 
@@ -178,7 +179,8 @@ struct erdma_resource_cb {
 enum {
 	ERDMA_RES_TYPE_PD = 0,
 	ERDMA_RES_TYPE_STAG_IDX = 1,
-	ERDMA_RES_CNT = 2,
+	ERDMA_RES_TYPE_AH = 2,
+	ERDMA_RES_CNT = 3,
 };
 
 struct erdma_dev {
diff --git a/drivers/infiniband/hw/erdma/erdma_hw.h b/drivers/infiniband/hw/erdma/erdma_hw.h
index f7f9dcac3ab0..64d856494359 100644
--- a/drivers/infiniband/hw/erdma/erdma_hw.h
+++ b/drivers/infiniband/hw/erdma/erdma_hw.h
@@ -9,6 +9,7 @@
 
 #include <linux/kernel.h>
 #include <linux/types.h>
+#include <linux/if_ether.h>
 
 /* PCIe device related definition. */
 #define ERDMA_PCI_WIDTH 64
@@ -150,6 +151,8 @@ enum CMDQ_RDMA_OPCODE {
 	CMDQ_OPCODE_REG_MR = 8,
 	CMDQ_OPCODE_DEREG_MR = 9,
 	CMDQ_OPCODE_SET_GID = 14,
+	CMDQ_OPCODE_CREATE_AH = 15,
+	CMDQ_OPCODE_DESTROY_AH = 16,
 };
 
 enum CMDQ_COMMON_OPCODE {
@@ -297,6 +300,36 @@ struct erdma_cmdq_dereg_mr_req {
 	u32 cfg;
 };
 
+/* create_av cfg0 */
+#define ERDMA_CMD_CREATE_AV_FL_MASK GENMASK(19, 0)
+#define ERDMA_CMD_CREATE_AV_NTYPE_MASK BIT(20)
+
+struct erdma_av_cfg {
+	u32 cfg0;
+	u8 traffic_class;
+	u8 hop_limit;
+	u8 sl;
+	u8 rsvd;
+	u16 udp_sport;
+	u16 sgid_index;
+	u8 dmac[ETH_ALEN];
+	u8 padding[2];
+	u8 dgid[ERDMA_ROCEV2_GID_SIZE];
+};
+
+struct erdma_cmdq_create_ah_req {
+	u64 hdr;
+	u32 pdn;
+	u32 ahn;
+	struct erdma_av_cfg av_cfg;
+};
+
+struct erdma_cmdq_destroy_ah_req {
+	u64 hdr;
+	u32 pdn;
+	u32 ahn;
+};
+
 /* modify qp cfg */
 #define ERDMA_CMD_MODIFY_QP_STATE_MASK GENMASK(31, 24)
 #define ERDMA_CMD_MODIFY_QP_CC_MASK GENMASK(23, 20)
@@ -433,6 +466,7 @@ struct erdma_cmdq_set_gid_req {
 #define ERDMA_CMD_DEV_CAP_MAX_CQE_MASK GENMASK_ULL(47, 40)
 #define ERDMA_CMD_DEV_CAP_FLAGS_MASK GENMASK_ULL(31, 24)
 #define ERDMA_CMD_DEV_CAP_MAX_RECV_WR_MASK GENMASK_ULL(23, 16)
+#define ERDMA_CMD_DEV_CAP_MAX_AH_MASK GENMASK_ULL(15, 8)
 #define ERDMA_CMD_DEV_CAP_MAX_MR_SIZE_MASK GENMASK_ULL(7, 0)
 
 /* cap qword 1 definition */
diff --git a/drivers/infiniband/hw/erdma/erdma_main.c b/drivers/infiniband/hw/erdma/erdma_main.c
index fca5bf7519dd..8d24b87cfce3 100644
--- a/drivers/infiniband/hw/erdma/erdma_main.c
+++ b/drivers/infiniband/hw/erdma/erdma_main.c
@@ -405,6 +405,7 @@ static int erdma_dev_attrs_init(struct erdma_dev *dev)
 	dev->attrs.max_mw = 1 << ERDMA_GET_CAP(MAX_MW, cap1);
 	dev->attrs.max_recv_wr = 1 << ERDMA_GET_CAP(MAX_RECV_WR, cap0);
 	dev->attrs.max_gid = 1 << ERDMA_GET_CAP(MAX_GID, cap0);
+	dev->attrs.max_ah = 1 << ERDMA_GET_CAP(MAX_AH, cap0);
 	dev->attrs.local_dma_key = ERDMA_GET_CAP(DMA_LOCAL_KEY, cap1);
 	dev->attrs.cc = ERDMA_GET_CAP(DEFAULT_CC, cap1);
 	dev->attrs.max_qp = ERDMA_NQP_PER_QBLOCK * ERDMA_GET_CAP(QBLOCK, cap1);
@@ -422,6 +423,7 @@ static int erdma_dev_attrs_init(struct erdma_dev *dev)
 
 	dev->res_cb[ERDMA_RES_TYPE_PD].max_cap = ERDMA_MAX_PD;
 	dev->res_cb[ERDMA_RES_TYPE_STAG_IDX].max_cap = dev->attrs.max_mr;
+	dev->res_cb[ERDMA_RES_TYPE_AH].max_cap = dev->attrs.max_ah;
 
 	erdma_cmdq_build_reqhdr(&req_hdr, CMDQ_SUBMOD_COMMON,
 				CMDQ_OPCODE_QUERY_FW_INFO);
@@ -486,6 +488,8 @@ static const struct ib_device_ops erdma_device_ops_rocev2 = {
 	.add_gid = erdma_add_gid,
 	.del_gid = erdma_del_gid,
 	.query_pkey = erdma_query_pkey,
+	.create_ah = erdma_create_ah,
+	.destroy_ah = erdma_destroy_ah,
 };
 
 static const struct ib_device_ops erdma_device_ops_iwarp = {
diff --git a/drivers/infiniband/hw/erdma/erdma_verbs.c b/drivers/infiniband/hw/erdma/erdma_verbs.c
index 03ea52bb233e..1fdf38f65b05 100644
--- a/drivers/infiniband/hw/erdma/erdma_verbs.c
+++ b/drivers/infiniband/hw/erdma/erdma_verbs.c
@@ -336,8 +336,10 @@ int erdma_query_device(struct ib_device *ibdev, struct ib_device_attr *attr,
 	attr->max_fast_reg_page_list_len = ERDMA_MAX_FRMR_PA;
 	attr->page_size_cap = ERDMA_PAGE_SIZE_SUPPORT;
 
-	if (erdma_device_rocev2(dev))
+	if (erdma_device_rocev2(dev)) {
 		attr->max_pkeys = ERDMA_MAX_PKEYS;
+		attr->max_ah = dev->attrs.max_ah;
+	}
 
 	if (dev->attrs.cap_flags & ERDMA_DEV_CAP_FLAGS_ATOMIC)
 		attr->atomic_cap = IB_ATOMIC_GLOB;
@@ -1917,3 +1919,134 @@ int erdma_query_pkey(struct ib_device *ibdev, u32 port, u16 index, u16 *pkey)
 	*pkey = ERDMA_DEFAULT_PKEY;
 	return 0;
 }
+
+static void erdma_attr_to_av(const struct rdma_ah_attr *ah_attr,
+			     struct erdma_av *av, u16 sport)
+{
+	const struct ib_global_route *grh = rdma_ah_read_grh(ah_attr);
+
+	av->port = rdma_ah_get_port_num(ah_attr);
+	av->sgid_index = grh->sgid_index;
+	av->hop_limit = grh->hop_limit;
+	av->traffic_class = grh->traffic_class;
+	av->sl = rdma_ah_get_sl(ah_attr);
+
+	av->flow_label = grh->flow_label;
+	av->udp_sport = sport;
+
+	ether_addr_copy(av->dmac, ah_attr->roce.dmac);
+	memcpy(av->dgid, grh->dgid.raw, ERDMA_ROCEV2_GID_SIZE);
+
+	if (ipv6_addr_v4mapped((struct in6_addr *)&grh->dgid))
+		av->ntype = ERDMA_NETWORK_TYPE_IPV4;
+	else
+		av->ntype = ERDMA_NETWORK_TYPE_IPV6;
+}
+
+static void erdma_av_to_attr(struct erdma_av *av, struct rdma_ah_attr *attr)
+{
+	attr->type = RDMA_AH_ATTR_TYPE_ROCE;
+
+	rdma_ah_set_sl(attr, av->sl);
+	rdma_ah_set_port_num(attr, av->port);
+	rdma_ah_set_ah_flags(attr, IB_AH_GRH);
+
+	rdma_ah_set_grh(attr, NULL, av->flow_label, av->sgid_index,
+			av->hop_limit, av->traffic_class);
+	rdma_ah_set_dgid_raw(attr, av->dgid);
+}
+
+static void erdma_set_av_cfg(struct erdma_av_cfg *av_cfg, struct erdma_av *av)
+{
+	av_cfg->cfg0 = FIELD_PREP(ERDMA_CMD_CREATE_AV_FL_MASK, av->flow_label) |
+		       FIELD_PREP(ERDMA_CMD_CREATE_AV_NTYPE_MASK, av->ntype);
+
+	av_cfg->traffic_class = av->traffic_class;
+	av_cfg->hop_limit = av->hop_limit;
+	av_cfg->sl = av->sl;
+
+	av_cfg->udp_sport = av->udp_sport;
+	av_cfg->sgid_index = av->sgid_index;
+
+	ether_addr_copy(av_cfg->dmac, av->dmac);
+	memcpy(av_cfg->dgid, av->dgid, ERDMA_ROCEV2_GID_SIZE);
+}
+
+int erdma_create_ah(struct ib_ah *ibah, struct rdma_ah_init_attr *init_attr,
+		    struct ib_udata *udata)
+{
+	const struct ib_global_route *grh =
+		rdma_ah_read_grh(init_attr->ah_attr);
+	struct erdma_dev *dev = to_edev(ibah->device);
+	struct erdma_pd *pd = to_epd(ibah->pd);
+	struct erdma_ah *ah = to_eah(ibah);
+	struct erdma_cmdq_create_ah_req req;
+	u32 udp_sport;
+	int ret;
+
+	ret = erdma_check_gid_attr(grh->sgid_attr);
+	if (ret)
+		return ret;
+
+	ret = erdma_alloc_idx(&dev->res_cb[ERDMA_RES_TYPE_AH]);
+	if (ret < 0)
+		return ret;
+
+	ah->ahn = ret;
+
+	if (grh->flow_label)
+		udp_sport = rdma_flow_label_to_udp_sport(grh->flow_label);
+	else
+		udp_sport =
+			IB_ROCE_UDP_ENCAP_VALID_PORT_MIN + (ah->ahn & 0x3FFF);
+
+	erdma_attr_to_av(init_attr->ah_attr, &ah->av, udp_sport);
+
+	erdma_cmdq_build_reqhdr(&req.hdr, CMDQ_SUBMOD_RDMA,
+				CMDQ_OPCODE_CREATE_AH);
+
+	req.pdn = pd->pdn;
+	req.ahn = ah->ahn;
+	erdma_set_av_cfg(&req.av_cfg, &ah->av);
+
+	ret = erdma_post_cmd_wait(&dev->cmdq, &req, sizeof(req), NULL, NULL);
+	if (ret) {
+		erdma_free_idx(&dev->res_cb[ERDMA_RES_TYPE_AH], ah->ahn);
+		return ret;
+	}
+
+	return 0;
+}
+
+int erdma_destroy_ah(struct ib_ah *ibah, u32 flags)
+{
+	struct erdma_dev *dev = to_edev(ibah->device);
+	struct erdma_pd *pd = to_epd(ibah->pd);
+	struct erdma_ah *ah = to_eah(ibah);
+	struct erdma_cmdq_destroy_ah_req req;
+	int ret;
+
+	erdma_cmdq_build_reqhdr(&req.hdr, CMDQ_SUBMOD_RDMA,
+				CMDQ_OPCODE_DESTROY_AH);
+
+	req.pdn = pd->pdn;
+	req.ahn = ah->ahn;
+
+	ret = erdma_post_cmd_wait(&dev->cmdq, &req, sizeof(req), NULL, NULL);
+	if (ret)
+		return ret;
+
+	erdma_free_idx(&dev->res_cb[ERDMA_RES_TYPE_AH], ah->ahn);
+
+	return 0;
+}
+
+int erdma_query_ah(struct ib_ah *ibah, struct rdma_ah_attr *ah_attr)
+{
+	struct erdma_ah *ah = to_eah(ibah);
+
+	memset(ah_attr, 0, sizeof(*ah_attr));
+	erdma_av_to_attr(&ah->av, ah_attr);
+
+	return 0;
+}
diff --git a/drivers/infiniband/hw/erdma/erdma_verbs.h b/drivers/infiniband/hw/erdma/erdma_verbs.h
index 1ae6ba56f597..78a6c35cf1a5 100644
--- a/drivers/infiniband/hw/erdma/erdma_verbs.h
+++ b/drivers/infiniband/hw/erdma/erdma_verbs.h
@@ -136,6 +136,25 @@ struct erdma_user_dbrecords_page {
 	int refcnt;
 };
 
+struct erdma_av {
+	u8 port;
+	u8 hop_limit;
+	u8 traffic_class;
+	u8 sl;
+	u8 sgid_index;
+	u16 udp_sport;
+	u32 flow_label;
+	u8 dmac[ETH_ALEN];
+	u8 dgid[ERDMA_ROCEV2_GID_SIZE];
+	enum erdma_network_type ntype;
+};
+
+struct erdma_ah {
+	struct ib_ah ibah;
+	struct erdma_av av;
+	u32 ahn;
+};
+
 struct erdma_uqp {
 	struct erdma_mem sq_mem;
 	struct erdma_mem rq_mem;
@@ -326,6 +345,11 @@ static inline struct erdma_cq *to_ecq(struct ib_cq *ibcq)
 	return container_of(ibcq, struct erdma_cq, ibcq);
 }
 
+static inline struct erdma_ah *to_eah(struct ib_ah *ibah)
+{
+	return container_of(ibah, struct erdma_ah, ibah);
+}
+
 static inline int erdma_check_gid_attr(const struct ib_gid_attr *attr)
 {
 	u8 ntype = rdma_gid_attr_network_type(attr);
@@ -395,5 +419,9 @@ enum rdma_link_layer erdma_get_link_layer(struct ib_device *ibdev,
 int erdma_add_gid(const struct ib_gid_attr *attr, void **context);
 int erdma_del_gid(const struct ib_gid_attr *attr, void **context);
 int erdma_query_pkey(struct ib_device *ibdev, u32 port, u16 index, u16 *pkey);
+int erdma_create_ah(struct ib_ah *ibah, struct rdma_ah_init_attr *init_attr,
+		    struct ib_udata *udata);
+int erdma_destroy_ah(struct ib_ah *ibah, u32 flags);
+int erdma_query_ah(struct ib_ah *ibah, struct rdma_ah_attr *ah_attr);
 
 #endif
-- 
2.43.5


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH for-next 5/8] RDMA/erdma: Add erdma_modify_qp_rocev2() interface
  2024-11-26  6:59 [PATCH for-next 0/8] RDMA/erdma: Support the RoCEv2 protocol Boshi Yu
                   ` (3 preceding siblings ...)
  2024-11-26  6:59 ` [PATCH for-next 4/8] RDMA/erdma: Add address handle implementation Boshi Yu
@ 2024-11-26  6:59 ` Boshi Yu
  2024-11-26  6:59 ` [PATCH for-next 6/8] RDMA/erdma: Reformat the code of the modify_qp interface Boshi Yu
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 21+ messages in thread
From: Boshi Yu @ 2024-11-26  6:59 UTC (permalink / raw)
  To: jgg, leon; +Cc: linux-rdma, kaishen, chengyou

The QP state machines in the RoCEv2 and iWARP protocols are
different. To handle these differences for the erdma RoCEv2
device, we provide the erdma_modify_qp_rocev2() interface,
which transitions the QP state and modifies QP attributes
accordingly.

Signed-off-by: Boshi Yu <boshiyu@linux.alibaba.com>
Reviewed-by: Cheng Xu <chengyou@linux.alibaba.com>
---
 drivers/infiniband/hw/erdma/erdma_cq.c    |  45 ++++++
 drivers/infiniband/hw/erdma/erdma_hw.h    |  14 ++
 drivers/infiniband/hw/erdma/erdma_main.c  |   3 +-
 drivers/infiniband/hw/erdma/erdma_qp.c    |  92 +++++++++++++
 drivers/infiniband/hw/erdma/erdma_verbs.c | 160 +++++++++++++++++++++-
 drivers/infiniband/hw/erdma/erdma_verbs.h |  46 +++++++
 6 files changed, 352 insertions(+), 8 deletions(-)

diff --git a/drivers/infiniband/hw/erdma/erdma_cq.c b/drivers/infiniband/hw/erdma/erdma_cq.c
index 70f89f0162aa..eada882472a3 100644
--- a/drivers/infiniband/hw/erdma/erdma_cq.c
+++ b/drivers/infiniband/hw/erdma/erdma_cq.c
@@ -201,3 +201,48 @@ int erdma_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *wc)
 
 	return npolled;
 }
+
+void erdma_remove_cqes_of_qp(struct ib_cq *ibcq, u32 qpn)
+{
+	struct erdma_cq *cq = to_ecq(ibcq);
+	struct erdma_cqe *cqe, *dst_cqe;
+	u32 prev_cq_ci, cur_cq_ci;
+	u32 ncqe = 0, nqp_cqe = 0;
+	unsigned long flags;
+	u8 owner;
+
+	spin_lock_irqsave(&cq->kern_cq.lock, flags);
+
+	prev_cq_ci = cq->kern_cq.ci;
+
+	while (ncqe < cq->depth && (cqe = get_next_valid_cqe(cq)) != NULL) {
+		++cq->kern_cq.ci;
+		++ncqe;
+	}
+
+	while (ncqe > 0) {
+		cur_cq_ci = prev_cq_ci + ncqe - 1;
+		cqe = get_queue_entry(cq->kern_cq.qbuf, cur_cq_ci, cq->depth,
+				      CQE_SHIFT);
+
+		if (be32_to_cpu(cqe->qpn) == qpn) {
+			++nqp_cqe;
+		} else if (nqp_cqe) {
+			dst_cqe = get_queue_entry(cq->kern_cq.qbuf,
+						  cur_cq_ci + nqp_cqe,
+						  cq->depth, CQE_SHIFT);
+			owner = FIELD_GET(ERDMA_CQE_HDR_OWNER_MASK,
+					  be32_to_cpu(dst_cqe->hdr));
+			cqe->hdr = cpu_to_be32(
+				(be32_to_cpu(cqe->hdr) &
+				 ~ERDMA_CQE_HDR_OWNER_MASK) |
+				FIELD_PREP(ERDMA_CQE_HDR_OWNER_MASK, owner));
+			memcpy(dst_cqe, cqe, sizeof(*cqe));
+		}
+
+		--ncqe;
+	}
+
+	cq->kern_cq.ci = prev_cq_ci + nqp_cqe;
+	spin_unlock_irqrestore(&cq->kern_cq.lock, flags);
+}
diff --git a/drivers/infiniband/hw/erdma/erdma_hw.h b/drivers/infiniband/hw/erdma/erdma_hw.h
index 64d856494359..b5c1aca71144 100644
--- a/drivers/infiniband/hw/erdma/erdma_hw.h
+++ b/drivers/infiniband/hw/erdma/erdma_hw.h
@@ -347,6 +347,20 @@ struct erdma_cmdq_modify_qp_req {
 	u32 recv_nxt;
 };
 
+/* modify qp cfg1 for roce device */
+#define ERDMA_CMD_MODIFY_QP_DQPN_MASK GENMASK(19, 0)
+
+struct erdma_cmdq_mod_qp_req_rocev2 {
+	u64 hdr;
+	u32 cfg0;
+	u32 cfg1;
+	u32 attr_mask;
+	u32 qkey;
+	u32 rq_psn;
+	u32 sq_psn;
+	struct erdma_av_cfg av_cfg;
+};
+
 /* create qp cfg0 */
 #define ERDMA_CMD_CREATE_QP_SQ_DEPTH_MASK GENMASK(31, 20)
 #define ERDMA_CMD_CREATE_QP_QPN_MASK GENMASK(19, 0)
diff --git a/drivers/infiniband/hw/erdma/erdma_main.c b/drivers/infiniband/hw/erdma/erdma_main.c
index 8d24b87cfce3..212007f939fc 100644
--- a/drivers/infiniband/hw/erdma/erdma_main.c
+++ b/drivers/infiniband/hw/erdma/erdma_main.c
@@ -490,6 +490,7 @@ static const struct ib_device_ops erdma_device_ops_rocev2 = {
 	.query_pkey = erdma_query_pkey,
 	.create_ah = erdma_create_ah,
 	.destroy_ah = erdma_destroy_ah,
+	.modify_qp = erdma_modify_qp_rocev2,
 };
 
 static const struct ib_device_ops erdma_device_ops_iwarp = {
@@ -501,6 +502,7 @@ static const struct ib_device_ops erdma_device_ops_iwarp = {
 	.iw_get_qp = erdma_get_ibqp,
 	.iw_reject = erdma_reject,
 	.iw_rem_ref = erdma_qp_put_ref,
+	.modify_qp = erdma_modify_qp,
 };
 
 static const struct ib_device_ops erdma_device_ops = {
@@ -526,7 +528,6 @@ static const struct ib_device_ops erdma_device_ops = {
 	.map_mr_sg = erdma_map_mr_sg,
 	.mmap = erdma_mmap,
 	.mmap_free = erdma_mmap_free,
-	.modify_qp = erdma_modify_qp,
 	.post_recv = erdma_post_recv,
 	.post_send = erdma_post_send,
 	.poll_cq = erdma_poll_cq,
diff --git a/drivers/infiniband/hw/erdma/erdma_qp.c b/drivers/infiniband/hw/erdma/erdma_qp.c
index 4d1f9114cd97..13977f4e9463 100644
--- a/drivers/infiniband/hw/erdma/erdma_qp.c
+++ b/drivers/infiniband/hw/erdma/erdma_qp.c
@@ -186,6 +186,98 @@ int erdma_modify_qp_internal(struct erdma_qp *qp, struct erdma_qp_attrs *attrs,
 	return ret;
 }
 
+static int modify_qp_cmd_rocev2(struct erdma_qp *qp,
+				struct erdma_mod_qp_params_rocev2 *params,
+				enum erdma_qpa_mask_rocev2 attr_mask)
+{
+	struct erdma_cmdq_mod_qp_req_rocev2 req;
+
+	memset(&req, 0, sizeof(req));
+
+	erdma_cmdq_build_reqhdr(&req.hdr, CMDQ_SUBMOD_RDMA,
+				CMDQ_OPCODE_MODIFY_QP);
+
+	req.cfg0 = FIELD_PREP(ERDMA_CMD_MODIFY_QP_QPN_MASK, QP_ID(qp));
+
+	if (attr_mask & ERDMA_QPA_ROCEV2_STATE)
+		req.cfg0 |= FIELD_PREP(ERDMA_CMD_MODIFY_QP_STATE_MASK,
+				       params->state);
+
+	if (attr_mask & ERDMA_QPA_ROCEV2_DST_QPN)
+		req.cfg1 = FIELD_PREP(ERDMA_CMD_MODIFY_QP_DQPN_MASK,
+				      params->dst_qpn);
+
+	if (attr_mask & ERDMA_QPA_ROCEV2_QKEY)
+		req.qkey = params->qkey;
+
+	if (attr_mask & ERDMA_QPA_ROCEV2_AV)
+		erdma_set_av_cfg(&req.av_cfg, &params->av);
+
+	if (attr_mask & ERDMA_QPA_ROCEV2_SQ_PSN)
+		req.sq_psn = params->sq_psn;
+
+	if (attr_mask & ERDMA_QPA_ROCEV2_RQ_PSN)
+		req.rq_psn = params->rq_psn;
+
+	req.attr_mask = attr_mask;
+
+	return erdma_post_cmd_wait(&qp->dev->cmdq, &req, sizeof(req), NULL,
+				   NULL);
+}
+
+static void erdma_reset_qp(struct erdma_qp *qp)
+{
+	qp->kern_qp.sq_pi = 0;
+	qp->kern_qp.sq_ci = 0;
+	qp->kern_qp.rq_pi = 0;
+	qp->kern_qp.rq_ci = 0;
+	memset(qp->kern_qp.swr_tbl, 0, qp->attrs.sq_size * sizeof(u64));
+	memset(qp->kern_qp.rwr_tbl, 0, qp->attrs.rq_size * sizeof(u64));
+	memset(qp->kern_qp.sq_buf, 0, qp->attrs.sq_size << SQEBB_SHIFT);
+	memset(qp->kern_qp.rq_buf, 0, qp->attrs.rq_size << RQE_SHIFT);
+	erdma_remove_cqes_of_qp(&qp->scq->ibcq, QP_ID(qp));
+	if (qp->rcq != qp->scq)
+		erdma_remove_cqes_of_qp(&qp->rcq->ibcq, QP_ID(qp));
+}
+
+int erdma_modify_qp_state_rocev2(struct erdma_qp *qp,
+				 struct erdma_mod_qp_params_rocev2 *params,
+				 int attr_mask)
+{
+	struct erdma_dev *dev = to_edev(qp->ibqp.device);
+	int ret;
+
+	ret = modify_qp_cmd_rocev2(qp, params, attr_mask);
+	if (ret)
+		return ret;
+
+	if (attr_mask & ERDMA_QPA_ROCEV2_STATE)
+		qp->attrs.rocev2.state = params->state;
+
+	if (attr_mask & ERDMA_QPA_ROCEV2_QKEY)
+		qp->attrs.rocev2.qkey = params->qkey;
+
+	if (attr_mask & ERDMA_QPA_ROCEV2_DST_QPN)
+		qp->attrs.rocev2.dst_qpn = params->dst_qpn;
+
+	if (attr_mask & ERDMA_QPA_ROCEV2_AV)
+		memcpy(&qp->attrs.rocev2.av, &params->av,
+		       sizeof(struct erdma_av));
+
+	if (rdma_is_kernel_res(&qp->ibqp.res) &&
+	    params->state == ERDMA_QPS_ROCEV2_RESET)
+		erdma_reset_qp(qp);
+
+	if (rdma_is_kernel_res(&qp->ibqp.res) &&
+	    params->state == ERDMA_QPS_ROCEV2_ERROR) {
+		qp->flags |= ERDMA_QP_IN_FLUSHING;
+		mod_delayed_work(dev->reflush_wq, &qp->reflush_dwork,
+				 usecs_to_jiffies(100));
+	}
+
+	return 0;
+}
+
 static void erdma_qp_safe_free(struct kref *ref)
 {
 	struct erdma_qp *qp = container_of(ref, struct erdma_qp, ref);
diff --git a/drivers/infiniband/hw/erdma/erdma_verbs.c b/drivers/infiniband/hw/erdma/erdma_verbs.c
index 1fdf38f65b05..ed9dfcd88ef7 100644
--- a/drivers/infiniband/hw/erdma/erdma_verbs.c
+++ b/drivers/infiniband/hw/erdma/erdma_verbs.c
@@ -121,7 +121,7 @@ static int create_qp_cmd(struct erdma_ucontext *uctx, struct erdma_qp *qp)
 
 	err = erdma_post_cmd_wait(&dev->cmdq, &req, sizeof(req), &resp0,
 				  &resp1);
-	if (!err)
+	if (!err && erdma_device_iwarp(dev))
 		qp->attrs.cookie =
 			FIELD_GET(ERDMA_CMDQ_CREATE_QP_RESP_COOKIE_MASK, resp0);
 
@@ -1017,7 +1017,12 @@ int erdma_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs,
 
 	qp->attrs.max_send_sge = attrs->cap.max_send_sge;
 	qp->attrs.max_recv_sge = attrs->cap.max_recv_sge;
-	qp->attrs.state = ERDMA_QP_STATE_IDLE;
+
+	if (erdma_device_iwarp(qp->dev))
+		qp->attrs.state = ERDMA_QP_STATE_IDLE;
+	else
+		qp->attrs.rocev2.state = ERDMA_QPS_ROCEV2_RESET;
+
 	INIT_DELAYED_WORK(&qp->reflush_dwork, erdma_flush_worker);
 
 	ret = create_qp_cmd(uctx, qp);
@@ -1291,13 +1296,20 @@ int erdma_destroy_qp(struct ib_qp *ibqp, struct ib_udata *udata)
 	struct erdma_dev *dev = to_edev(ibqp->device);
 	struct erdma_ucontext *ctx = rdma_udata_to_drv_context(
 		udata, struct erdma_ucontext, ibucontext);
+	struct erdma_mod_qp_params_rocev2 rocev2_params;
 	struct erdma_qp_attrs qp_attrs;
 	int err;
 	struct erdma_cmdq_destroy_qp_req req;
 
 	down_write(&qp->state_lock);
-	qp_attrs.state = ERDMA_QP_STATE_ERROR;
-	erdma_modify_qp_internal(qp, &qp_attrs, ERDMA_QP_ATTR_STATE);
+	if (erdma_device_iwarp(dev)) {
+		qp_attrs.state = ERDMA_QP_STATE_ERROR;
+		erdma_modify_qp_internal(qp, &qp_attrs, ERDMA_QP_ATTR_STATE);
+	} else {
+		rocev2_params.state = ERDMA_QPS_ROCEV2_ERROR;
+		erdma_modify_qp_state_rocev2(qp, &rocev2_params,
+					     ERDMA_QPA_ROCEV2_STATE);
+	}
 	up_write(&qp->state_lock);
 
 	cancel_delayed_work_sync(&qp->reflush_dwork);
@@ -1538,6 +1550,140 @@ static int ib_qp_state_to_erdma_qp_state[IB_QPS_ERR + 1] = {
 	[IB_QPS_ERR] = ERDMA_QP_STATE_ERROR
 };
 
+static int ib_qps_to_erdma_qps_rocev2[IB_QPS_ERR + 1] = {
+	[IB_QPS_RESET] = ERDMA_QPS_ROCEV2_RESET,
+	[IB_QPS_INIT] = ERDMA_QPS_ROCEV2_INIT,
+	[IB_QPS_RTR] = ERDMA_QPS_ROCEV2_RTR,
+	[IB_QPS_RTS] = ERDMA_QPS_ROCEV2_RTS,
+	[IB_QPS_SQD] = ERDMA_QPS_ROCEV2_SQD,
+	[IB_QPS_SQE] = ERDMA_QPS_ROCEV2_SQE,
+	[IB_QPS_ERR] = ERDMA_QPS_ROCEV2_ERROR,
+};
+
+static int erdma_qps_to_ib_qps_rocev2[ERDMA_QPS_ROCEV2_COUNT] = {
+	[ERDMA_QPS_ROCEV2_RESET] = IB_QPS_RESET,
+	[ERDMA_QPS_ROCEV2_INIT] = IB_QPS_INIT,
+	[ERDMA_QPS_ROCEV2_RTR] = IB_QPS_RTR,
+	[ERDMA_QPS_ROCEV2_RTS] = IB_QPS_RTS,
+	[ERDMA_QPS_ROCEV2_SQD] = IB_QPS_SQD,
+	[ERDMA_QPS_ROCEV2_SQE] = IB_QPS_SQE,
+	[ERDMA_QPS_ROCEV2_ERROR] = IB_QPS_ERR,
+};
+
+static int erdma_check_qp_attr_rocev2(struct erdma_qp *qp,
+				      struct ib_qp_attr *attr, int attr_mask)
+{
+	enum ib_qp_state cur_state, nxt_state;
+	struct erdma_dev *dev = qp->dev;
+	int ret = -EINVAL;
+
+	if (attr_mask & ~IB_QP_ATTR_STANDARD_BITS) {
+		ret = -EOPNOTSUPP;
+		goto out;
+	}
+
+	if ((attr_mask & IB_QP_PKEY_INDEX) &&
+	    attr->pkey_index >= ERDMA_MAX_PKEYS)
+		goto out;
+
+	if ((attr_mask & IB_QP_PORT) &&
+	    !rdma_is_port_valid(&dev->ibdev, attr->port_num))
+		goto out;
+
+	cur_state = (attr_mask & IB_QP_CUR_STATE) ?
+			    attr->cur_qp_state :
+			    erdma_qps_to_ib_qps_rocev2[qp->attrs.rocev2.state];
+
+	nxt_state = (attr_mask & IB_QP_STATE) ? attr->qp_state : cur_state;
+
+	if (!ib_modify_qp_is_ok(cur_state, nxt_state, qp->ibqp.qp_type,
+				attr_mask))
+		goto out;
+
+	if ((attr_mask & IB_QP_AV) &&
+	    erdma_check_gid_attr(rdma_ah_read_grh(&attr->ah_attr)->sgid_attr))
+		goto out;
+
+	return 0;
+
+out:
+	return ret;
+}
+
+static void erdma_init_mod_qp_params_rocev2(
+	struct erdma_qp *qp, struct erdma_mod_qp_params_rocev2 *params,
+	int *erdma_attr_mask, struct ib_qp_attr *attr, int ib_attr_mask)
+{
+	enum erdma_qpa_mask_rocev2 to_modify_attrs = 0;
+	enum erdma_qps_rocev2 cur_state, nxt_state;
+	u16 udp_sport;
+
+	if (ib_attr_mask & IB_QP_CUR_STATE)
+		cur_state = ib_qps_to_erdma_qps_rocev2[attr->cur_qp_state];
+	else
+		cur_state = qp->attrs.rocev2.state;
+
+	if (ib_attr_mask & IB_QP_STATE)
+		nxt_state = ib_qps_to_erdma_qps_rocev2[attr->qp_state];
+	else
+		nxt_state = cur_state;
+
+	to_modify_attrs |= ERDMA_QPA_ROCEV2_STATE;
+	params->state = nxt_state;
+
+	if (ib_attr_mask & IB_QP_QKEY) {
+		to_modify_attrs |= ERDMA_QPA_ROCEV2_QKEY;
+		params->qkey = attr->qkey;
+	}
+
+	if (ib_attr_mask & IB_QP_SQ_PSN) {
+		to_modify_attrs |= ERDMA_QPA_ROCEV2_SQ_PSN;
+		params->sq_psn = attr->sq_psn;
+	}
+
+	if (ib_attr_mask & IB_QP_RQ_PSN) {
+		to_modify_attrs |= ERDMA_QPA_ROCEV2_RQ_PSN;
+		params->rq_psn = attr->rq_psn;
+	}
+
+	if (ib_attr_mask & IB_QP_DEST_QPN) {
+		to_modify_attrs |= ERDMA_QPA_ROCEV2_DST_QPN;
+		params->dst_qpn = attr->dest_qp_num;
+	}
+
+	if (ib_attr_mask & IB_QP_AV) {
+		to_modify_attrs |= ERDMA_QPA_ROCEV2_AV;
+		udp_sport = rdma_get_udp_sport(attr->ah_attr.grh.flow_label,
+					       QP_ID(qp), params->dst_qpn);
+		erdma_attr_to_av(&attr->ah_attr, &params->av, udp_sport);
+	}
+
+	*erdma_attr_mask = to_modify_attrs;
+}
+
+int erdma_modify_qp_rocev2(struct ib_qp *ibqp, struct ib_qp_attr *attr,
+			   int attr_mask, struct ib_udata *udata)
+{
+	struct erdma_mod_qp_params_rocev2 params;
+	struct erdma_qp *qp = to_eqp(ibqp);
+	int ret = 0, erdma_attr_mask = 0;
+
+	down_write(&qp->state_lock);
+
+	ret = erdma_check_qp_attr_rocev2(qp, attr, attr_mask);
+	if (ret)
+		goto out;
+
+	erdma_init_mod_qp_params_rocev2(qp, &params, &erdma_attr_mask, attr,
+					attr_mask);
+
+	ret = erdma_modify_qp_state_rocev2(qp, &params, erdma_attr_mask);
+
+out:
+	up_write(&qp->state_lock);
+	return ret;
+}
+
 int erdma_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask,
 		    struct ib_udata *udata)
 {
@@ -1920,8 +2066,8 @@ int erdma_query_pkey(struct ib_device *ibdev, u32 port, u16 index, u16 *pkey)
 	return 0;
 }
 
-static void erdma_attr_to_av(const struct rdma_ah_attr *ah_attr,
-			     struct erdma_av *av, u16 sport)
+void erdma_attr_to_av(const struct rdma_ah_attr *ah_attr, struct erdma_av *av,
+		      u16 sport)
 {
 	const struct ib_global_route *grh = rdma_ah_read_grh(ah_attr);
 
@@ -1956,7 +2102,7 @@ static void erdma_av_to_attr(struct erdma_av *av, struct rdma_ah_attr *attr)
 	rdma_ah_set_dgid_raw(attr, av->dgid);
 }
 
-static void erdma_set_av_cfg(struct erdma_av_cfg *av_cfg, struct erdma_av *av)
+void erdma_set_av_cfg(struct erdma_av_cfg *av_cfg, struct erdma_av *av)
 {
 	av_cfg->cfg0 = FIELD_PREP(ERDMA_CMD_CREATE_AV_FL_MASK, av->flow_label) |
 		       FIELD_PREP(ERDMA_CMD_CREATE_AV_NTYPE_MASK, av->ntype);
diff --git a/drivers/infiniband/hw/erdma/erdma_verbs.h b/drivers/infiniband/hw/erdma/erdma_verbs.h
index 78a6c35cf1a5..60fcb702fda7 100644
--- a/drivers/infiniband/hw/erdma/erdma_verbs.h
+++ b/drivers/infiniband/hw/erdma/erdma_verbs.h
@@ -216,10 +216,46 @@ enum erdma_qp_attr_mask {
 	ERDMA_QP_ATTR_MPA = (1 << 7)
 };
 
+enum erdma_qps_rocev2 {
+	ERDMA_QPS_ROCEV2_RESET = 0,
+	ERDMA_QPS_ROCEV2_INIT = 1,
+	ERDMA_QPS_ROCEV2_RTR = 2,
+	ERDMA_QPS_ROCEV2_RTS = 3,
+	ERDMA_QPS_ROCEV2_SQD = 4,
+	ERDMA_QPS_ROCEV2_SQE = 5,
+	ERDMA_QPS_ROCEV2_ERROR = 6,
+	ERDMA_QPS_ROCEV2_COUNT = 7,
+};
+
+enum erdma_qpa_mask_rocev2 {
+	ERDMA_QPA_ROCEV2_STATE = (1 << 0),
+	ERDMA_QPA_ROCEV2_QKEY = (1 << 1),
+	ERDMA_QPA_ROCEV2_AV = (1 << 2),
+	ERDMA_QPA_ROCEV2_SQ_PSN = (1 << 3),
+	ERDMA_QPA_ROCEV2_RQ_PSN = (1 << 4),
+	ERDMA_QPA_ROCEV2_DST_QPN = (1 << 5),
+};
+
 enum erdma_qp_flags {
 	ERDMA_QP_IN_FLUSHING = (1 << 0),
 };
 
+struct erdma_mod_qp_params_rocev2 {
+	enum erdma_qps_rocev2 state;
+	u32 qkey;
+	u32 sq_psn;
+	u32 rq_psn;
+	u32 dst_qpn;
+	struct erdma_av av;
+};
+
+struct erdma_qp_attrs_rocev2 {
+	enum erdma_qps_rocev2 state;
+	u32 qkey;
+	u32 dst_qpn;
+	struct erdma_av av;
+};
+
 struct erdma_qp_attrs {
 	enum erdma_qp_state state;
 	enum erdma_cc_alg cc; /* Congestion control algorithm */
@@ -234,6 +270,7 @@ struct erdma_qp_attrs {
 #define ERDMA_QP_PASSIVE 1
 	u8 qp_type;
 	u8 pd_len;
+	struct erdma_qp_attrs_rocev2 rocev2;
 };
 
 struct erdma_qp {
@@ -386,6 +423,11 @@ int erdma_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int mask,
 		   struct ib_qp_init_attr *init_attr);
 int erdma_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int mask,
 		    struct ib_udata *data);
+int erdma_modify_qp_state_rocev2(struct erdma_qp *qp,
+				 struct erdma_mod_qp_params_rocev2 *params,
+				 int attr_mask);
+int erdma_modify_qp_rocev2(struct ib_qp *ibqp, struct ib_qp_attr *attr,
+			   int mask, struct ib_udata *udata);
 int erdma_destroy_qp(struct ib_qp *ibqp, struct ib_udata *udata);
 int erdma_destroy_cq(struct ib_cq *ibcq, struct ib_udata *udata);
 void erdma_disassociate_ucontext(struct ib_ucontext *ibcontext);
@@ -404,6 +446,7 @@ int erdma_post_send(struct ib_qp *ibqp, const struct ib_send_wr *send_wr,
 int erdma_post_recv(struct ib_qp *ibqp, const struct ib_recv_wr *recv_wr,
 		    const struct ib_recv_wr **bad_recv_wr);
 int erdma_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *wc);
+void erdma_remove_cqes_of_qp(struct ib_cq *ibcq, u32 qpn);
 struct ib_mr *erdma_ib_alloc_mr(struct ib_pd *ibpd, enum ib_mr_type mr_type,
 				u32 max_num_sg);
 int erdma_map_mr_sg(struct ib_mr *ibmr, struct scatterlist *sg, int sg_nents,
@@ -419,6 +462,9 @@ enum rdma_link_layer erdma_get_link_layer(struct ib_device *ibdev,
 int erdma_add_gid(const struct ib_gid_attr *attr, void **context);
 int erdma_del_gid(const struct ib_gid_attr *attr, void **context);
 int erdma_query_pkey(struct ib_device *ibdev, u32 port, u16 index, u16 *pkey);
+void erdma_attr_to_av(const struct rdma_ah_attr *ah_attr, struct erdma_av *av,
+		      u16 sport);
+void erdma_set_av_cfg(struct erdma_av_cfg *av_cfg, struct erdma_av *av);
 int erdma_create_ah(struct ib_ah *ibah, struct rdma_ah_init_attr *init_attr,
 		    struct ib_udata *udata);
 int erdma_destroy_ah(struct ib_ah *ibah, u32 flags);
-- 
2.43.5


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH for-next 6/8] RDMA/erdma: Reformat the code of the modify_qp interface
  2024-11-26  6:59 [PATCH for-next 0/8] RDMA/erdma: Support the RoCEv2 protocol Boshi Yu
                   ` (4 preceding siblings ...)
  2024-11-26  6:59 ` [PATCH for-next 5/8] RDMA/erdma: Add erdma_modify_qp_rocev2() interface Boshi Yu
@ 2024-11-26  6:59 ` Boshi Yu
  2024-11-26  6:59 ` [PATCH for-next 7/8] RDMA/erdma: Add the query_qp command to the cmdq Boshi Yu
  2024-11-26  6:59 ` [PATCH for-next 8/8] RDMA/erdma: Support UD QPs and UD WRs Boshi Yu
  7 siblings, 0 replies; 21+ messages in thread
From: Boshi Yu @ 2024-11-26  6:59 UTC (permalink / raw)
  To: jgg, leon; +Cc: linux-rdma, kaishen, chengyou

The procedure for modifying QP is similar for both the iWARP and
RoCEv2 protocols. Therefore, we unify the code and provide the
erdma_modify_qp() interface for both protocols.

Signed-off-by: Boshi Yu <boshiyu@linux.alibaba.com>
Reviewed-by: Cheng Xu <chengyou@linux.alibaba.com>
---
 drivers/infiniband/hw/erdma/erdma_cm.c    |  71 ++++----
 drivers/infiniband/hw/erdma/erdma_hw.h    |   1 +
 drivers/infiniband/hw/erdma/erdma_main.c  |   3 +-
 drivers/infiniband/hw/erdma/erdma_qp.c    | 136 ++++++++------
 drivers/infiniband/hw/erdma/erdma_verbs.c | 210 +++++++++++-----------
 drivers/infiniband/hw/erdma/erdma_verbs.h |  73 +++++---
 6 files changed, 276 insertions(+), 218 deletions(-)

diff --git a/drivers/infiniband/hw/erdma/erdma_cm.c b/drivers/infiniband/hw/erdma/erdma_cm.c
index 771059a8eb7d..1b23c698ec25 100644
--- a/drivers/infiniband/hw/erdma/erdma_cm.c
+++ b/drivers/infiniband/hw/erdma/erdma_cm.c
@@ -567,7 +567,8 @@ static int erdma_proc_mpareq(struct erdma_cep *cep)
 
 static int erdma_proc_mpareply(struct erdma_cep *cep)
 {
-	struct erdma_qp_attrs qp_attrs;
+	enum erdma_qpa_mask_iwarp to_modify_attrs = 0;
+	struct erdma_mod_qp_params_iwarp params;
 	struct erdma_qp *qp = cep->qp;
 	struct mpa_rr *rep;
 	int ret;
@@ -597,26 +598,29 @@ static int erdma_proc_mpareply(struct erdma_cep *cep)
 		return -EINVAL;
 	}
 
-	memset(&qp_attrs, 0, sizeof(qp_attrs));
-	qp_attrs.irq_size = cep->ird;
-	qp_attrs.orq_size = cep->ord;
-	qp_attrs.state = ERDMA_QP_STATE_RTS;
+	memset(&params, 0, sizeof(params));
+	params.state = ERDMA_QPS_IWARP_RTS;
+	params.irq_size = cep->ird;
+	params.orq_size = cep->ord;
 
 	down_write(&qp->state_lock);
-	if (qp->attrs.state > ERDMA_QP_STATE_RTR) {
+	if (qp->attrs.iwarp.state > ERDMA_QPS_IWARP_RTR) {
 		ret = -EINVAL;
 		up_write(&qp->state_lock);
 		goto out_err;
 	}
 
-	qp->attrs.qp_type = ERDMA_QP_ACTIVE;
-	if (__mpa_ext_cc(cep->mpa.ext_data.bits) != qp->attrs.cc)
-		qp->attrs.cc = COMPROMISE_CC;
+	to_modify_attrs = ERDMA_QPA_IWARP_STATE | ERDMA_QPA_IWARP_LLP_HANDLE |
+			  ERDMA_QPA_IWARP_MPA | ERDMA_QPA_IWARP_IRD |
+			  ERDMA_QPA_IWARP_ORD;
 
-	ret = erdma_modify_qp_internal(qp, &qp_attrs,
-				       ERDMA_QP_ATTR_STATE |
-				       ERDMA_QP_ATTR_LLP_HANDLE |
-				       ERDMA_QP_ATTR_MPA);
+	params.qp_type = ERDMA_QP_ACTIVE;
+	if (__mpa_ext_cc(cep->mpa.ext_data.bits) != qp->attrs.cc) {
+		to_modify_attrs |= ERDMA_QPA_IWARP_CC;
+		params.cc = COMPROMISE_CC;
+	}
+
+	ret = erdma_modify_qp_state_iwarp(qp, &params, to_modify_attrs);
 
 	up_write(&qp->state_lock);
 
@@ -722,7 +726,7 @@ static int erdma_newconn_connected(struct erdma_cep *cep)
 	__mpa_rr_set_revision(&cep->mpa.hdr.params.bits, MPA_REVISION_EXT_1);
 
 	memcpy(cep->mpa.hdr.key, MPA_KEY_REQ, MPA_KEY_SIZE);
-	cep->mpa.ext_data.cookie = cpu_to_be32(cep->qp->attrs.cookie);
+	cep->mpa.ext_data.cookie = cpu_to_be32(cep->qp->attrs.iwarp.cookie);
 	__mpa_ext_set_cc(&cep->mpa.ext_data.bits, cep->qp->attrs.cc);
 
 	ret = erdma_send_mpareqrep(cep, cep->private_data, cep->pd_len);
@@ -1126,10 +1130,11 @@ int erdma_connect(struct iw_cm_id *id, struct iw_cm_conn_param *params)
 
 int erdma_accept(struct iw_cm_id *id, struct iw_cm_conn_param *params)
 {
-	struct erdma_dev *dev = to_edev(id->device);
 	struct erdma_cep *cep = (struct erdma_cep *)id->provider_data;
+	struct erdma_mod_qp_params_iwarp mod_qp_params;
+	enum erdma_qpa_mask_iwarp to_modify_attrs = 0;
+	struct erdma_dev *dev = to_edev(id->device);
 	struct erdma_qp *qp;
-	struct erdma_qp_attrs qp_attrs;
 	int ret;
 
 	erdma_cep_set_inuse(cep);
@@ -1156,7 +1161,7 @@ int erdma_accept(struct iw_cm_id *id, struct iw_cm_conn_param *params)
 	erdma_qp_get(qp);
 
 	down_write(&qp->state_lock);
-	if (qp->attrs.state > ERDMA_QP_STATE_RTR) {
+	if (qp->attrs.iwarp.state > ERDMA_QPS_IWARP_RTR) {
 		ret = -EINVAL;
 		up_write(&qp->state_lock);
 		goto error;
@@ -1181,11 +1186,11 @@ int erdma_accept(struct iw_cm_id *id, struct iw_cm_conn_param *params)
 	cep->cm_id = id;
 	id->add_ref(id);
 
-	memset(&qp_attrs, 0, sizeof(qp_attrs));
-	qp_attrs.orq_size = params->ord;
-	qp_attrs.irq_size = params->ird;
+	memset(&mod_qp_params, 0, sizeof(mod_qp_params));
 
-	qp_attrs.state = ERDMA_QP_STATE_RTS;
+	mod_qp_params.irq_size = params->ird;
+	mod_qp_params.orq_size = params->ord;
+	mod_qp_params.state = ERDMA_QPS_IWARP_RTS;
 
 	/* Associate QP with CEP */
 	erdma_cep_get(cep);
@@ -1194,19 +1199,21 @@ int erdma_accept(struct iw_cm_id *id, struct iw_cm_conn_param *params)
 
 	cep->state = ERDMA_EPSTATE_RDMA_MODE;
 
-	qp->attrs.qp_type = ERDMA_QP_PASSIVE;
-	qp->attrs.pd_len = params->private_data_len;
+	mod_qp_params.qp_type = ERDMA_QP_PASSIVE;
+	mod_qp_params.pd_len = params->private_data_len;
 
-	if (qp->attrs.cc != __mpa_ext_cc(cep->mpa.ext_data.bits))
-		qp->attrs.cc = COMPROMISE_CC;
+	to_modify_attrs = ERDMA_QPA_IWARP_STATE | ERDMA_QPA_IWARP_ORD |
+			  ERDMA_QPA_IWARP_LLP_HANDLE | ERDMA_QPA_IWARP_IRD |
+			  ERDMA_QPA_IWARP_MPA;
+
+	if (qp->attrs.cc != __mpa_ext_cc(cep->mpa.ext_data.bits)) {
+		to_modify_attrs |= ERDMA_QPA_IWARP_CC;
+		mod_qp_params.cc = COMPROMISE_CC;
+	}
 
 	/* move to rts */
-	ret = erdma_modify_qp_internal(qp, &qp_attrs,
-				       ERDMA_QP_ATTR_STATE |
-				       ERDMA_QP_ATTR_ORD |
-				       ERDMA_QP_ATTR_LLP_HANDLE |
-				       ERDMA_QP_ATTR_IRD |
-				       ERDMA_QP_ATTR_MPA);
+	ret = erdma_modify_qp_state_iwarp(qp, &mod_qp_params, to_modify_attrs);
+
 	up_write(&qp->state_lock);
 
 	if (ret)
@@ -1214,7 +1221,7 @@ int erdma_accept(struct iw_cm_id *id, struct iw_cm_conn_param *params)
 
 	cep->mpa.ext_data.bits = 0;
 	__mpa_ext_set_cc(&cep->mpa.ext_data.bits, qp->attrs.cc);
-	cep->mpa.ext_data.cookie = cpu_to_be32(cep->qp->attrs.cookie);
+	cep->mpa.ext_data.cookie = cpu_to_be32(cep->qp->attrs.iwarp.cookie);
 
 	ret = erdma_send_mpareqrep(cep, params->private_data,
 				   params->private_data_len);
diff --git a/drivers/infiniband/hw/erdma/erdma_hw.h b/drivers/infiniband/hw/erdma/erdma_hw.h
index b5c1aca71144..3b0f7fc4ff31 100644
--- a/drivers/infiniband/hw/erdma/erdma_hw.h
+++ b/drivers/infiniband/hw/erdma/erdma_hw.h
@@ -31,6 +31,7 @@
 enum erdma_proto_type {
 	ERDMA_PROTO_IWARP = 0,
 	ERDMA_PROTO_ROCEV2 = 1,
+	ERDMA_PROTO_COUNT = 2,
 };
 
 /* PCIe Bar0 Registers. */
diff --git a/drivers/infiniband/hw/erdma/erdma_main.c b/drivers/infiniband/hw/erdma/erdma_main.c
index 212007f939fc..6c7a4f6232f4 100644
--- a/drivers/infiniband/hw/erdma/erdma_main.c
+++ b/drivers/infiniband/hw/erdma/erdma_main.c
@@ -490,7 +490,6 @@ static const struct ib_device_ops erdma_device_ops_rocev2 = {
 	.query_pkey = erdma_query_pkey,
 	.create_ah = erdma_create_ah,
 	.destroy_ah = erdma_destroy_ah,
-	.modify_qp = erdma_modify_qp_rocev2,
 };
 
 static const struct ib_device_ops erdma_device_ops_iwarp = {
@@ -502,7 +501,6 @@ static const struct ib_device_ops erdma_device_ops_iwarp = {
 	.iw_get_qp = erdma_get_ibqp,
 	.iw_reject = erdma_reject,
 	.iw_rem_ref = erdma_qp_put_ref,
-	.modify_qp = erdma_modify_qp,
 };
 
 static const struct ib_device_ops erdma_device_ops = {
@@ -537,6 +535,7 @@ static const struct ib_device_ops erdma_device_ops = {
 	.query_qp = erdma_query_qp,
 	.req_notify_cq = erdma_req_notify_cq,
 	.reg_user_mr = erdma_reg_user_mr,
+	.modify_qp = erdma_modify_qp,
 
 	INIT_RDMA_OBJ_SIZE(ib_cq, erdma_cq, ibcq),
 	INIT_RDMA_OBJ_SIZE(ib_pd, erdma_pd, ibpd),
diff --git a/drivers/infiniband/hw/erdma/erdma_qp.c b/drivers/infiniband/hw/erdma/erdma_qp.c
index 13977f4e9463..03d93f026fca 100644
--- a/drivers/infiniband/hw/erdma/erdma_qp.c
+++ b/drivers/infiniband/hw/erdma/erdma_qp.c
@@ -11,20 +11,20 @@
 
 void erdma_qp_llp_close(struct erdma_qp *qp)
 {
-	struct erdma_qp_attrs qp_attrs;
+	struct erdma_mod_qp_params_iwarp params;
 
 	down_write(&qp->state_lock);
 
-	switch (qp->attrs.state) {
-	case ERDMA_QP_STATE_RTS:
-	case ERDMA_QP_STATE_RTR:
-	case ERDMA_QP_STATE_IDLE:
-	case ERDMA_QP_STATE_TERMINATE:
-		qp_attrs.state = ERDMA_QP_STATE_CLOSING;
-		erdma_modify_qp_internal(qp, &qp_attrs, ERDMA_QP_ATTR_STATE);
+	switch (qp->attrs.iwarp.state) {
+	case ERDMA_QPS_IWARP_RTS:
+	case ERDMA_QPS_IWARP_RTR:
+	case ERDMA_QPS_IWARP_IDLE:
+	case ERDMA_QPS_IWARP_TERMINATE:
+		params.state = ERDMA_QPS_IWARP_CLOSING;
+		erdma_modify_qp_state_iwarp(qp, &params, ERDMA_QPA_IWARP_STATE);
 		break;
-	case ERDMA_QP_STATE_CLOSING:
-		qp->attrs.state = ERDMA_QP_STATE_IDLE;
+	case ERDMA_QPS_IWARP_CLOSING:
+		qp->attrs.iwarp.state = ERDMA_QPS_IWARP_IDLE;
 		break;
 	default:
 		break;
@@ -48,9 +48,10 @@ struct ib_qp *erdma_get_ibqp(struct ib_device *ibdev, int id)
 	return NULL;
 }
 
-static int erdma_modify_qp_state_to_rts(struct erdma_qp *qp,
-					struct erdma_qp_attrs *attrs,
-					enum erdma_qp_attr_mask mask)
+static int
+erdma_modify_qp_state_to_rts(struct erdma_qp *qp,
+			     struct erdma_mod_qp_params_iwarp *params,
+			     enum erdma_qpa_mask_iwarp mask)
 {
 	int ret;
 	struct erdma_dev *dev = qp->dev;
@@ -59,12 +60,15 @@ static int erdma_modify_qp_state_to_rts(struct erdma_qp *qp,
 	struct erdma_cep *cep = qp->cep;
 	struct sockaddr_storage local_addr, remote_addr;
 
-	if (!(mask & ERDMA_QP_ATTR_LLP_HANDLE))
+	if (!(mask & ERDMA_QPA_IWARP_LLP_HANDLE))
 		return -EINVAL;
 
-	if (!(mask & ERDMA_QP_ATTR_MPA))
+	if (!(mask & ERDMA_QPA_IWARP_MPA))
 		return -EINVAL;
 
+	if (!(mask & ERDMA_QPA_IWARP_CC))
+		params->cc = qp->attrs.cc;
+
 	ret = getname_local(cep->sock, &local_addr);
 	if (ret < 0)
 		return ret;
@@ -73,18 +77,16 @@ static int erdma_modify_qp_state_to_rts(struct erdma_qp *qp,
 	if (ret < 0)
 		return ret;
 
-	qp->attrs.state = ERDMA_QP_STATE_RTS;
-
 	tp = tcp_sk(qp->cep->sock->sk);
 
 	erdma_cmdq_build_reqhdr(&req.hdr, CMDQ_SUBMOD_RDMA,
 				CMDQ_OPCODE_MODIFY_QP);
 
-	req.cfg = FIELD_PREP(ERDMA_CMD_MODIFY_QP_STATE_MASK, qp->attrs.state) |
-		  FIELD_PREP(ERDMA_CMD_MODIFY_QP_CC_MASK, qp->attrs.cc) |
+	req.cfg = FIELD_PREP(ERDMA_CMD_MODIFY_QP_STATE_MASK, params->state) |
+		  FIELD_PREP(ERDMA_CMD_MODIFY_QP_CC_MASK, params->cc) |
 		  FIELD_PREP(ERDMA_CMD_MODIFY_QP_QPN_MASK, QP_ID(qp));
 
-	req.cookie = be32_to_cpu(qp->cep->mpa.ext_data.cookie);
+	req.cookie = be32_to_cpu(cep->mpa.ext_data.cookie);
 	req.dip = to_sockaddr_in(remote_addr).sin_addr.s_addr;
 	req.sip = to_sockaddr_in(local_addr).sin_addr.s_addr;
 	req.dport = to_sockaddr_in(remote_addr).sin_port;
@@ -92,33 +94,55 @@ static int erdma_modify_qp_state_to_rts(struct erdma_qp *qp,
 
 	req.send_nxt = tp->snd_nxt;
 	/* rsvd tcp seq for mpa-rsp in server. */
-	if (qp->attrs.qp_type == ERDMA_QP_PASSIVE)
-		req.send_nxt += MPA_DEFAULT_HDR_LEN + qp->attrs.pd_len;
+	if (params->qp_type == ERDMA_QP_PASSIVE)
+		req.send_nxt += MPA_DEFAULT_HDR_LEN + params->pd_len;
 	req.recv_nxt = tp->rcv_nxt;
 
-	return erdma_post_cmd_wait(&dev->cmdq, &req, sizeof(req), NULL, NULL);
+	ret = erdma_post_cmd_wait(&dev->cmdq, &req, sizeof(req), NULL, NULL);
+	if (ret)
+		return ret;
+
+	if (mask & ERDMA_QPA_IWARP_IRD)
+		qp->attrs.irq_size = params->irq_size;
+
+	if (mask & ERDMA_QPA_IWARP_ORD)
+		qp->attrs.orq_size = params->orq_size;
+
+	if (mask & ERDMA_QPA_IWARP_CC)
+		qp->attrs.cc = params->cc;
+
+	qp->attrs.iwarp.state = ERDMA_QPS_IWARP_RTS;
+
+	return 0;
 }
 
-static int erdma_modify_qp_state_to_stop(struct erdma_qp *qp,
-					 struct erdma_qp_attrs *attrs,
-					 enum erdma_qp_attr_mask mask)
+static int
+erdma_modify_qp_state_to_stop(struct erdma_qp *qp,
+			      struct erdma_mod_qp_params_iwarp *params,
+			      enum erdma_qpa_mask_iwarp mask)
 {
 	struct erdma_dev *dev = qp->dev;
 	struct erdma_cmdq_modify_qp_req req;
-
-	qp->attrs.state = attrs->state;
+	int ret;
 
 	erdma_cmdq_build_reqhdr(&req.hdr, CMDQ_SUBMOD_RDMA,
 				CMDQ_OPCODE_MODIFY_QP);
 
-	req.cfg = FIELD_PREP(ERDMA_CMD_MODIFY_QP_STATE_MASK, attrs->state) |
+	req.cfg = FIELD_PREP(ERDMA_CMD_MODIFY_QP_STATE_MASK, params->state) |
 		  FIELD_PREP(ERDMA_CMD_MODIFY_QP_QPN_MASK, QP_ID(qp));
 
-	return erdma_post_cmd_wait(&dev->cmdq, &req, sizeof(req), NULL, NULL);
+	ret = erdma_post_cmd_wait(&dev->cmdq, &req, sizeof(req), NULL, NULL);
+	if (ret)
+		return ret;
+
+	qp->attrs.iwarp.state = params->state;
+
+	return 0;
 }
 
-int erdma_modify_qp_internal(struct erdma_qp *qp, struct erdma_qp_attrs *attrs,
-			     enum erdma_qp_attr_mask mask)
+int erdma_modify_qp_state_iwarp(struct erdma_qp *qp,
+				struct erdma_mod_qp_params_iwarp *params,
+				int mask)
 {
 	bool need_reflush = false;
 	int drop_conn, ret = 0;
@@ -126,31 +150,31 @@ int erdma_modify_qp_internal(struct erdma_qp *qp, struct erdma_qp_attrs *attrs,
 	if (!mask)
 		return 0;
 
-	if (!(mask & ERDMA_QP_ATTR_STATE))
+	if (!(mask & ERDMA_QPA_IWARP_STATE))
 		return 0;
 
-	switch (qp->attrs.state) {
-	case ERDMA_QP_STATE_IDLE:
-	case ERDMA_QP_STATE_RTR:
-		if (attrs->state == ERDMA_QP_STATE_RTS) {
-			ret = erdma_modify_qp_state_to_rts(qp, attrs, mask);
-		} else if (attrs->state == ERDMA_QP_STATE_ERROR) {
-			qp->attrs.state = ERDMA_QP_STATE_ERROR;
+	switch (qp->attrs.iwarp.state) {
+	case ERDMA_QPS_IWARP_IDLE:
+	case ERDMA_QPS_IWARP_RTR:
+		if (params->state == ERDMA_QPS_IWARP_RTS) {
+			ret = erdma_modify_qp_state_to_rts(qp, params, mask);
+		} else if (params->state == ERDMA_QPS_IWARP_ERROR) {
+			qp->attrs.iwarp.state = ERDMA_QPS_IWARP_ERROR;
 			need_reflush = true;
 			if (qp->cep) {
 				erdma_cep_put(qp->cep);
 				qp->cep = NULL;
 			}
-			ret = erdma_modify_qp_state_to_stop(qp, attrs, mask);
+			ret = erdma_modify_qp_state_to_stop(qp, params, mask);
 		}
 		break;
-	case ERDMA_QP_STATE_RTS:
+	case ERDMA_QPS_IWARP_RTS:
 		drop_conn = 0;
 
-		if (attrs->state == ERDMA_QP_STATE_CLOSING ||
-		    attrs->state == ERDMA_QP_STATE_TERMINATE ||
-		    attrs->state == ERDMA_QP_STATE_ERROR) {
-			ret = erdma_modify_qp_state_to_stop(qp, attrs, mask);
+		if (params->state == ERDMA_QPS_IWARP_CLOSING ||
+		    params->state == ERDMA_QPS_IWARP_TERMINATE ||
+		    params->state == ERDMA_QPS_IWARP_ERROR) {
+			ret = erdma_modify_qp_state_to_stop(qp, params, mask);
 			drop_conn = 1;
 			need_reflush = true;
 		}
@@ -159,17 +183,17 @@ int erdma_modify_qp_internal(struct erdma_qp *qp, struct erdma_qp_attrs *attrs,
 			erdma_qp_cm_drop(qp);
 
 		break;
-	case ERDMA_QP_STATE_TERMINATE:
-		if (attrs->state == ERDMA_QP_STATE_ERROR)
-			qp->attrs.state = ERDMA_QP_STATE_ERROR;
+	case ERDMA_QPS_IWARP_TERMINATE:
+		if (params->state == ERDMA_QPS_IWARP_ERROR)
+			qp->attrs.iwarp.state = ERDMA_QPS_IWARP_ERROR;
 		break;
-	case ERDMA_QP_STATE_CLOSING:
-		if (attrs->state == ERDMA_QP_STATE_IDLE) {
-			qp->attrs.state = ERDMA_QP_STATE_IDLE;
-		} else if (attrs->state == ERDMA_QP_STATE_ERROR) {
-			ret = erdma_modify_qp_state_to_stop(qp, attrs, mask);
-			qp->attrs.state = ERDMA_QP_STATE_ERROR;
-		} else if (attrs->state != ERDMA_QP_STATE_CLOSING) {
+	case ERDMA_QPS_IWARP_CLOSING:
+		if (params->state == ERDMA_QPS_IWARP_IDLE) {
+			qp->attrs.iwarp.state = ERDMA_QPS_IWARP_IDLE;
+		} else if (params->state == ERDMA_QPS_IWARP_ERROR) {
+			ret = erdma_modify_qp_state_to_stop(qp, params, mask);
+			qp->attrs.iwarp.state = ERDMA_QPS_IWARP_ERROR;
+		} else if (params->state != ERDMA_QPS_IWARP_CLOSING) {
 			return -ECONNABORTED;
 		}
 		break;
diff --git a/drivers/infiniband/hw/erdma/erdma_verbs.c b/drivers/infiniband/hw/erdma/erdma_verbs.c
index ed9dfcd88ef7..e382d6e243e9 100644
--- a/drivers/infiniband/hw/erdma/erdma_verbs.c
+++ b/drivers/infiniband/hw/erdma/erdma_verbs.c
@@ -122,7 +122,7 @@ static int create_qp_cmd(struct erdma_ucontext *uctx, struct erdma_qp *qp)
 	err = erdma_post_cmd_wait(&dev->cmdq, &req, sizeof(req), &resp0,
 				  &resp1);
 	if (!err && erdma_device_iwarp(dev))
-		qp->attrs.cookie =
+		qp->attrs.iwarp.cookie =
 			FIELD_GET(ERDMA_CMDQ_CREATE_QP_RESP_COOKIE_MASK, resp0);
 
 	return err;
@@ -1019,7 +1019,7 @@ int erdma_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs,
 	qp->attrs.max_recv_sge = attrs->cap.max_recv_sge;
 
 	if (erdma_device_iwarp(qp->dev))
-		qp->attrs.state = ERDMA_QP_STATE_IDLE;
+		qp->attrs.iwarp.state = ERDMA_QPS_IWARP_IDLE;
 	else
 		qp->attrs.rocev2.state = ERDMA_QPS_ROCEV2_RESET;
 
@@ -1296,18 +1296,18 @@ int erdma_destroy_qp(struct ib_qp *ibqp, struct ib_udata *udata)
 	struct erdma_dev *dev = to_edev(ibqp->device);
 	struct erdma_ucontext *ctx = rdma_udata_to_drv_context(
 		udata, struct erdma_ucontext, ibucontext);
-	struct erdma_mod_qp_params_rocev2 rocev2_params;
-	struct erdma_qp_attrs qp_attrs;
-	int err;
 	struct erdma_cmdq_destroy_qp_req req;
+	union erdma_mod_qp_params params;
+	int err;
 
 	down_write(&qp->state_lock);
 	if (erdma_device_iwarp(dev)) {
-		qp_attrs.state = ERDMA_QP_STATE_ERROR;
-		erdma_modify_qp_internal(qp, &qp_attrs, ERDMA_QP_ATTR_STATE);
+		params.iwarp.state = ERDMA_QPS_IWARP_ERROR;
+		erdma_modify_qp_state_iwarp(qp, &params.iwarp,
+					    ERDMA_QPA_IWARP_STATE);
 	} else {
-		rocev2_params.state = ERDMA_QPS_ROCEV2_ERROR;
-		erdma_modify_qp_state_rocev2(qp, &rocev2_params,
+		params.rocev2.state = ERDMA_QPS_ROCEV2_ERROR;
+		erdma_modify_qp_state_rocev2(qp, &params.rocev2,
 					     ERDMA_QPA_ROCEV2_STATE);
 	}
 	up_write(&qp->state_lock);
@@ -1540,38 +1540,69 @@ void erdma_dealloc_ucontext(struct ib_ucontext *ibctx)
 	atomic_dec(&dev->num_ctx);
 }
 
-static int ib_qp_state_to_erdma_qp_state[IB_QPS_ERR + 1] = {
-	[IB_QPS_RESET] = ERDMA_QP_STATE_IDLE,
-	[IB_QPS_INIT] = ERDMA_QP_STATE_IDLE,
-	[IB_QPS_RTR] = ERDMA_QP_STATE_RTR,
-	[IB_QPS_RTS] = ERDMA_QP_STATE_RTS,
-	[IB_QPS_SQD] = ERDMA_QP_STATE_CLOSING,
-	[IB_QPS_SQE] = ERDMA_QP_STATE_TERMINATE,
-	[IB_QPS_ERR] = ERDMA_QP_STATE_ERROR
+static int ib_qps_to_erdma_qps[ERDMA_PROTO_COUNT][IB_QPS_ERR + 1] = {
+	[ERDMA_PROTO_IWARP] = {
+		[IB_QPS_RESET] = ERDMA_QPS_IWARP_IDLE,
+		[IB_QPS_INIT] = ERDMA_QPS_IWARP_IDLE,
+		[IB_QPS_RTR] = ERDMA_QPS_IWARP_RTR,
+		[IB_QPS_RTS] = ERDMA_QPS_IWARP_RTS,
+		[IB_QPS_SQD] = ERDMA_QPS_IWARP_CLOSING,
+		[IB_QPS_SQE] = ERDMA_QPS_IWARP_TERMINATE,
+		[IB_QPS_ERR] = ERDMA_QPS_IWARP_ERROR,
+	},
+	[ERDMA_PROTO_ROCEV2] = {
+		[IB_QPS_RESET] = ERDMA_QPS_ROCEV2_RESET,
+		[IB_QPS_INIT] = ERDMA_QPS_ROCEV2_INIT,
+		[IB_QPS_RTR] = ERDMA_QPS_ROCEV2_RTR,
+		[IB_QPS_RTS] = ERDMA_QPS_ROCEV2_RTS,
+		[IB_QPS_SQD] = ERDMA_QPS_ROCEV2_SQD,
+		[IB_QPS_SQE] = ERDMA_QPS_ROCEV2_SQE,
+		[IB_QPS_ERR] = ERDMA_QPS_ROCEV2_ERROR,
+	},
 };
 
-static int ib_qps_to_erdma_qps_rocev2[IB_QPS_ERR + 1] = {
-	[IB_QPS_RESET] = ERDMA_QPS_ROCEV2_RESET,
-	[IB_QPS_INIT] = ERDMA_QPS_ROCEV2_INIT,
-	[IB_QPS_RTR] = ERDMA_QPS_ROCEV2_RTR,
-	[IB_QPS_RTS] = ERDMA_QPS_ROCEV2_RTS,
-	[IB_QPS_SQD] = ERDMA_QPS_ROCEV2_SQD,
-	[IB_QPS_SQE] = ERDMA_QPS_ROCEV2_SQE,
-	[IB_QPS_ERR] = ERDMA_QPS_ROCEV2_ERROR,
+static int erdma_qps_to_ib_qps[ERDMA_PROTO_COUNT][ERDMA_QPS_ROCEV2_COUNT] = {
+	[ERDMA_PROTO_IWARP] = {
+		[ERDMA_QPS_IWARP_IDLE] = IB_QPS_INIT,
+		[ERDMA_QPS_IWARP_RTR] = IB_QPS_RTR,
+		[ERDMA_QPS_IWARP_RTS] = IB_QPS_RTS,
+		[ERDMA_QPS_IWARP_CLOSING] = IB_QPS_ERR,
+		[ERDMA_QPS_IWARP_TERMINATE] = IB_QPS_ERR,
+		[ERDMA_QPS_IWARP_ERROR] = IB_QPS_ERR,
+	},
+	[ERDMA_PROTO_ROCEV2] = {
+		[ERDMA_QPS_ROCEV2_RESET] = IB_QPS_RESET,
+		[ERDMA_QPS_ROCEV2_INIT] = IB_QPS_INIT,
+		[ERDMA_QPS_ROCEV2_RTR] = IB_QPS_RTR,
+		[ERDMA_QPS_ROCEV2_RTS] = IB_QPS_RTS,
+		[ERDMA_QPS_ROCEV2_SQD] = IB_QPS_SQD,
+		[ERDMA_QPS_ROCEV2_SQE] = IB_QPS_SQE,
+		[ERDMA_QPS_ROCEV2_ERROR] = IB_QPS_ERR,
+	},
 };
 
-static int erdma_qps_to_ib_qps_rocev2[ERDMA_QPS_ROCEV2_COUNT] = {
-	[ERDMA_QPS_ROCEV2_RESET] = IB_QPS_RESET,
-	[ERDMA_QPS_ROCEV2_INIT] = IB_QPS_INIT,
-	[ERDMA_QPS_ROCEV2_RTR] = IB_QPS_RTR,
-	[ERDMA_QPS_ROCEV2_RTS] = IB_QPS_RTS,
-	[ERDMA_QPS_ROCEV2_SQD] = IB_QPS_SQD,
-	[ERDMA_QPS_ROCEV2_SQE] = IB_QPS_SQE,
-	[ERDMA_QPS_ROCEV2_ERROR] = IB_QPS_ERR,
-};
+static inline enum erdma_qps_iwarp ib_to_iwarp_qps(enum ib_qp_state state)
+{
+	return ib_qps_to_erdma_qps[ERDMA_PROTO_IWARP][state];
+}
 
-static int erdma_check_qp_attr_rocev2(struct erdma_qp *qp,
-				      struct ib_qp_attr *attr, int attr_mask)
+static inline enum erdma_qps_rocev2 ib_to_rocev2_qps(enum ib_qp_state state)
+{
+	return ib_qps_to_erdma_qps[ERDMA_PROTO_ROCEV2][state];
+}
+
+static inline enum ib_qp_state iwarp_to_ib_qps(enum erdma_qps_iwarp state)
+{
+	return erdma_qps_to_ib_qps[ERDMA_PROTO_IWARP][state];
+}
+
+static inline enum ib_qp_state rocev2_to_ib_qps(enum erdma_qps_rocev2 state)
+{
+	return erdma_qps_to_ib_qps[ERDMA_PROTO_ROCEV2][state];
+}
+
+static int erdma_check_qp_attrs(struct erdma_qp *qp, struct ib_qp_attr *attr,
+				int attr_mask)
 {
 	enum ib_qp_state cur_state, nxt_state;
 	struct erdma_dev *dev = qp->dev;
@@ -1582,27 +1613,31 @@ static int erdma_check_qp_attr_rocev2(struct erdma_qp *qp,
 		goto out;
 	}
 
-	if ((attr_mask & IB_QP_PKEY_INDEX) &&
-	    attr->pkey_index >= ERDMA_MAX_PKEYS)
-		goto out;
-
 	if ((attr_mask & IB_QP_PORT) &&
 	    !rdma_is_port_valid(&dev->ibdev, attr->port_num))
 		goto out;
 
-	cur_state = (attr_mask & IB_QP_CUR_STATE) ?
-			    attr->cur_qp_state :
-			    erdma_qps_to_ib_qps_rocev2[qp->attrs.rocev2.state];
+	if (erdma_device_rocev2(dev)) {
+		cur_state = (attr_mask & IB_QP_CUR_STATE) ?
+				    attr->cur_qp_state :
+				    rocev2_to_ib_qps(qp->attrs.rocev2.state);
 
-	nxt_state = (attr_mask & IB_QP_STATE) ? attr->qp_state : cur_state;
+		nxt_state = (attr_mask & IB_QP_STATE) ? attr->qp_state :
+							cur_state;
 
-	if (!ib_modify_qp_is_ok(cur_state, nxt_state, qp->ibqp.qp_type,
-				attr_mask))
-		goto out;
+		if (!ib_modify_qp_is_ok(cur_state, nxt_state, qp->ibqp.qp_type,
+					attr_mask))
+			goto out;
 
-	if ((attr_mask & IB_QP_AV) &&
-	    erdma_check_gid_attr(rdma_ah_read_grh(&attr->ah_attr)->sgid_attr))
-		goto out;
+		if ((attr_mask & IB_QP_AV) &&
+		    erdma_check_gid_attr(
+			    rdma_ah_read_grh(&attr->ah_attr)->sgid_attr))
+			goto out;
+
+		if ((attr_mask & IB_QP_PKEY_INDEX) &&
+		    attr->pkey_index >= ERDMA_MAX_PKEYS)
+			goto out;
+	}
 
 	return 0;
 
@@ -1619,12 +1654,12 @@ static void erdma_init_mod_qp_params_rocev2(
 	u16 udp_sport;
 
 	if (ib_attr_mask & IB_QP_CUR_STATE)
-		cur_state = ib_qps_to_erdma_qps_rocev2[attr->cur_qp_state];
+		cur_state = ib_to_rocev2_qps(attr->cur_qp_state);
 	else
 		cur_state = qp->attrs.rocev2.state;
 
 	if (ib_attr_mask & IB_QP_STATE)
-		nxt_state = ib_qps_to_erdma_qps_rocev2[attr->qp_state];
+		nxt_state = ib_to_rocev2_qps(attr->qp_state);
 	else
 		nxt_state = cur_state;
 
@@ -1661,75 +1696,46 @@ static void erdma_init_mod_qp_params_rocev2(
 	*erdma_attr_mask = to_modify_attrs;
 }
 
-int erdma_modify_qp_rocev2(struct ib_qp *ibqp, struct ib_qp_attr *attr,
-			   int attr_mask, struct ib_udata *udata)
+int erdma_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask,
+		    struct ib_udata *udata)
 {
-	struct erdma_mod_qp_params_rocev2 params;
 	struct erdma_qp *qp = to_eqp(ibqp);
+	union erdma_mod_qp_params params;
 	int ret = 0, erdma_attr_mask = 0;
 
 	down_write(&qp->state_lock);
 
-	ret = erdma_check_qp_attr_rocev2(qp, attr, attr_mask);
+	ret = erdma_check_qp_attrs(qp, attr, attr_mask);
 	if (ret)
 		goto out;
 
-	erdma_init_mod_qp_params_rocev2(qp, &params, &erdma_attr_mask, attr,
-					attr_mask);
-
-	ret = erdma_modify_qp_state_rocev2(qp, &params, erdma_attr_mask);
-
-out:
-	up_write(&qp->state_lock);
-	return ret;
-}
-
-int erdma_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask,
-		    struct ib_udata *udata)
-{
-	struct erdma_qp_attrs new_attrs;
-	enum erdma_qp_attr_mask erdma_attr_mask = 0;
-	struct erdma_qp *qp = to_eqp(ibqp);
-	int ret = 0;
-
-	if (attr_mask & ~IB_QP_ATTR_STANDARD_BITS)
-		return -EOPNOTSUPP;
-
-	memset(&new_attrs, 0, sizeof(new_attrs));
+	if (erdma_device_iwarp(qp->dev)) {
+		if (attr_mask & IB_QP_STATE) {
+			erdma_attr_mask |= ERDMA_QPA_IWARP_STATE;
+			params.iwarp.state = ib_to_iwarp_qps(attr->qp_state);
+		}
 
-	if (attr_mask & IB_QP_STATE) {
-		new_attrs.state = ib_qp_state_to_erdma_qp_state[attr->qp_state];
+		ret = erdma_modify_qp_state_iwarp(qp, &params.iwarp,
+						  erdma_attr_mask);
+	} else {
+		erdma_init_mod_qp_params_rocev2(
+			qp, &params.rocev2, &erdma_attr_mask, attr, attr_mask);
 
-		erdma_attr_mask |= ERDMA_QP_ATTR_STATE;
+		ret = erdma_modify_qp_state_rocev2(qp, &params.rocev2,
+						   erdma_attr_mask);
 	}
 
-	down_write(&qp->state_lock);
-
-	ret = erdma_modify_qp_internal(qp, &new_attrs, erdma_attr_mask);
-
+out:
 	up_write(&qp->state_lock);
-
 	return ret;
 }
 
 static enum ib_qp_state query_qp_state(struct erdma_qp *qp)
 {
-	switch (qp->attrs.state) {
-	case ERDMA_QP_STATE_IDLE:
-		return IB_QPS_INIT;
-	case ERDMA_QP_STATE_RTR:
-		return IB_QPS_RTR;
-	case ERDMA_QP_STATE_RTS:
-		return IB_QPS_RTS;
-	case ERDMA_QP_STATE_CLOSING:
-		return IB_QPS_ERR;
-	case ERDMA_QP_STATE_TERMINATE:
-		return IB_QPS_ERR;
-	case ERDMA_QP_STATE_ERROR:
-		return IB_QPS_ERR;
-	default:
-		return IB_QPS_ERR;
-	}
+	if (erdma_device_iwarp(qp->dev))
+		return iwarp_to_ib_qps(qp->attrs.iwarp.state);
+	else
+		return rocev2_to_ib_qps(qp->attrs.rocev2.state);
 }
 
 int erdma_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr,
diff --git a/drivers/infiniband/hw/erdma/erdma_verbs.h b/drivers/infiniband/hw/erdma/erdma_verbs.h
index 60fcb702fda7..5d8cbac76434 100644
--- a/drivers/infiniband/hw/erdma/erdma_verbs.h
+++ b/drivers/infiniband/hw/erdma/erdma_verbs.h
@@ -195,25 +195,26 @@ struct erdma_kqp {
 	u8 sig_all;
 };
 
-enum erdma_qp_state {
-	ERDMA_QP_STATE_IDLE = 0,
-	ERDMA_QP_STATE_RTR = 1,
-	ERDMA_QP_STATE_RTS = 2,
-	ERDMA_QP_STATE_CLOSING = 3,
-	ERDMA_QP_STATE_TERMINATE = 4,
-	ERDMA_QP_STATE_ERROR = 5,
-	ERDMA_QP_STATE_UNDEF = 7,
-	ERDMA_QP_STATE_COUNT = 8
+enum erdma_qps_iwarp {
+	ERDMA_QPS_IWARP_IDLE = 0,
+	ERDMA_QPS_IWARP_RTR = 1,
+	ERDMA_QPS_IWARP_RTS = 2,
+	ERDMA_QPS_IWARP_CLOSING = 3,
+	ERDMA_QPS_IWARP_TERMINATE = 4,
+	ERDMA_QPS_IWARP_ERROR = 5,
+	ERDMA_QPS_IWARP_UNDEF = 6,
+	ERDMA_QPS_IWARP_COUNT = 7,
 };
 
-enum erdma_qp_attr_mask {
-	ERDMA_QP_ATTR_STATE = (1 << 0),
-	ERDMA_QP_ATTR_LLP_HANDLE = (1 << 2),
-	ERDMA_QP_ATTR_ORD = (1 << 3),
-	ERDMA_QP_ATTR_IRD = (1 << 4),
-	ERDMA_QP_ATTR_SQ_SIZE = (1 << 5),
-	ERDMA_QP_ATTR_RQ_SIZE = (1 << 6),
-	ERDMA_QP_ATTR_MPA = (1 << 7)
+enum erdma_qpa_mask_iwarp {
+	ERDMA_QPA_IWARP_STATE = (1 << 0),
+	ERDMA_QPA_IWARP_LLP_HANDLE = (1 << 2),
+	ERDMA_QPA_IWARP_ORD = (1 << 3),
+	ERDMA_QPA_IWARP_IRD = (1 << 4),
+	ERDMA_QPA_IWARP_SQ_SIZE = (1 << 5),
+	ERDMA_QPA_IWARP_RQ_SIZE = (1 << 6),
+	ERDMA_QPA_IWARP_MPA = (1 << 7),
+	ERDMA_QPA_IWARP_CC = (1 << 8),
 };
 
 enum erdma_qps_rocev2 {
@@ -240,6 +241,23 @@ enum erdma_qp_flags {
 	ERDMA_QP_IN_FLUSHING = (1 << 0),
 };
 
+#define ERDMA_QP_ACTIVE 0
+#define ERDMA_QP_PASSIVE 1
+
+struct erdma_mod_qp_params_iwarp {
+	enum erdma_qps_iwarp state;
+	enum erdma_cc_alg cc;
+	u8 qp_type;
+	u8 pd_len;
+	u32 irq_size;
+	u32 orq_size;
+};
+
+struct erdma_qp_attrs_iwarp {
+	enum erdma_qps_iwarp state;
+	u32 cookie;
+};
+
 struct erdma_mod_qp_params_rocev2 {
 	enum erdma_qps_rocev2 state;
 	u32 qkey;
@@ -249,6 +267,11 @@ struct erdma_mod_qp_params_rocev2 {
 	struct erdma_av av;
 };
 
+union erdma_mod_qp_params {
+	struct erdma_mod_qp_params_iwarp iwarp;
+	struct erdma_mod_qp_params_rocev2 rocev2;
+};
+
 struct erdma_qp_attrs_rocev2 {
 	enum erdma_qps_rocev2 state;
 	u32 qkey;
@@ -257,7 +280,6 @@ struct erdma_qp_attrs_rocev2 {
 };
 
 struct erdma_qp_attrs {
-	enum erdma_qp_state state;
 	enum erdma_cc_alg cc; /* Congestion control algorithm */
 	u32 sq_size;
 	u32 rq_size;
@@ -265,12 +287,10 @@ struct erdma_qp_attrs {
 	u32 irq_size;
 	u32 max_send_sge;
 	u32 max_recv_sge;
-	u32 cookie;
-#define ERDMA_QP_ACTIVE 0
-#define ERDMA_QP_PASSIVE 1
-	u8 qp_type;
-	u8 pd_len;
-	struct erdma_qp_attrs_rocev2 rocev2;
+	union {
+		struct erdma_qp_attrs_iwarp iwarp;
+		struct erdma_qp_attrs_rocev2 rocev2;
+	};
 };
 
 struct erdma_qp {
@@ -342,8 +362,9 @@ static inline struct erdma_cq *find_cq_by_cqn(struct erdma_dev *dev, int id)
 
 void erdma_qp_get(struct erdma_qp *qp);
 void erdma_qp_put(struct erdma_qp *qp);
-int erdma_modify_qp_internal(struct erdma_qp *qp, struct erdma_qp_attrs *attrs,
-			     enum erdma_qp_attr_mask mask);
+int erdma_modify_qp_state_iwarp(struct erdma_qp *qp,
+				struct erdma_mod_qp_params_iwarp *params,
+				int mask);
 void erdma_qp_llp_close(struct erdma_qp *qp);
 void erdma_qp_cm_drop(struct erdma_qp *qp);
 
-- 
2.43.5


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH for-next 7/8] RDMA/erdma: Add the query_qp command to the cmdq
  2024-11-26  6:59 [PATCH for-next 0/8] RDMA/erdma: Support the RoCEv2 protocol Boshi Yu
                   ` (5 preceding siblings ...)
  2024-11-26  6:59 ` [PATCH for-next 6/8] RDMA/erdma: Reformat the code of the modify_qp interface Boshi Yu
@ 2024-11-26  6:59 ` Boshi Yu
  2024-11-26  6:59 ` [PATCH for-next 8/8] RDMA/erdma: Support UD QPs and UD WRs Boshi Yu
  7 siblings, 0 replies; 21+ messages in thread
From: Boshi Yu @ 2024-11-26  6:59 UTC (permalink / raw)
  To: jgg, leon; +Cc: linux-rdma, kaishen, chengyou

Certian QP attributes, such as sq_draining, can only be obtained
by querying the hardware on the erdma RoCEv2 device. To address this,
we add the query_qp command to the cmdq and parse the response to
retrieve corresponding QP attributes.

Signed-off-by: Boshi Yu <boshiyu@linux.alibaba.com>
Reviewed-by: Cheng Xu <chengyou@linux.alibaba.com>
---
 drivers/infiniband/hw/erdma/erdma_hw.h    | 12 +++++++
 drivers/infiniband/hw/erdma/erdma_verbs.c | 38 +++++++++++++++++++++--
 drivers/infiniband/hw/erdma/erdma_verbs.h |  1 +
 3 files changed, 48 insertions(+), 3 deletions(-)

diff --git a/drivers/infiniband/hw/erdma/erdma_hw.h b/drivers/infiniband/hw/erdma/erdma_hw.h
index 3b0f7fc4ff31..809e77dde271 100644
--- a/drivers/infiniband/hw/erdma/erdma_hw.h
+++ b/drivers/infiniband/hw/erdma/erdma_hw.h
@@ -154,6 +154,7 @@ enum CMDQ_RDMA_OPCODE {
 	CMDQ_OPCODE_SET_GID = 14,
 	CMDQ_OPCODE_CREATE_AH = 15,
 	CMDQ_OPCODE_DESTROY_AH = 16,
+	CMDQ_OPCODE_QUERY_QP = 17,
 };
 
 enum CMDQ_COMMON_OPCODE {
@@ -362,6 +363,17 @@ struct erdma_cmdq_mod_qp_req_rocev2 {
 	struct erdma_av_cfg av_cfg;
 };
 
+/* query qp response mask */
+#define ERDMA_CMD_QUERY_QP_RESP_SQ_PSN_MASK GENMASK_ULL(23, 0)
+#define ERDMA_CMD_QUERY_QP_RESP_RQ_PSN_MASK GENMASK_ULL(47, 24)
+#define ERDMA_CMD_QUERY_QP_RESP_QP_STATE_MASK GENMASK_ULL(55, 48)
+#define ERDMA_CMD_QUERY_QP_RESP_SQ_DRAINING_MASK GENMASK_ULL(56, 56)
+
+struct erdma_cmdq_query_qp_req_rocev2 {
+	u64 hdr;
+	u32 qpn;
+};
+
 /* create qp cfg0 */
 #define ERDMA_CMD_CREATE_QP_SQ_DEPTH_MASK GENMASK(31, 20)
 #define ERDMA_CMD_CREATE_QP_QPN_MASK GENMASK(19, 0)
diff --git a/drivers/infiniband/hw/erdma/erdma_verbs.c b/drivers/infiniband/hw/erdma/erdma_verbs.c
index e382d6e243e9..28b792c31059 100644
--- a/drivers/infiniband/hw/erdma/erdma_verbs.c
+++ b/drivers/infiniband/hw/erdma/erdma_verbs.c
@@ -1741,8 +1741,11 @@ static enum ib_qp_state query_qp_state(struct erdma_qp *qp)
 int erdma_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr,
 		   int qp_attr_mask, struct ib_qp_init_attr *qp_init_attr)
 {
+	struct erdma_cmdq_query_qp_req_rocev2 req;
 	struct erdma_dev *dev;
 	struct erdma_qp *qp;
+	u64 resp;
+	int ret;
 
 	if (ibqp && qp_attr && qp_init_attr) {
 		qp = to_eqp(ibqp);
@@ -1769,8 +1772,37 @@ int erdma_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr,
 
 	qp_init_attr->cap = qp_attr->cap;
 
-	qp_attr->qp_state = query_qp_state(qp);
-	qp_attr->cur_qp_state = query_qp_state(qp);
+	if (erdma_device_rocev2(dev)) {
+		/* Query hardware to get some attributes */
+		erdma_cmdq_build_reqhdr(&req.hdr, CMDQ_SUBMOD_RDMA,
+					CMDQ_OPCODE_QUERY_QP);
+		req.qpn = QP_ID(qp);
+
+		ret = erdma_post_cmd_wait(&dev->cmdq, &req, sizeof(req), &resp,
+					  NULL);
+		if (ret)
+			return ret;
+
+		qp_attr->sq_psn =
+			FIELD_GET(ERDMA_CMD_QUERY_QP_RESP_SQ_PSN_MASK, resp);
+		qp_attr->rq_psn =
+			FIELD_GET(ERDMA_CMD_QUERY_QP_RESP_RQ_PSN_MASK, resp);
+		qp_attr->qp_state = rocev2_to_ib_qps(
+			FIELD_GET(ERDMA_CMD_QUERY_QP_RESP_QP_STATE_MASK, resp));
+		qp_attr->cur_qp_state = qp_attr->qp_state;
+		qp_attr->sq_draining = FIELD_GET(
+			ERDMA_CMD_QUERY_QP_RESP_SQ_DRAINING_MASK, resp);
+
+		qp_attr->pkey_index = 0;
+		qp_attr->dest_qp_num = qp->attrs.rocev2.dst_qpn;
+
+		if (qp->ibqp.qp_type == IB_QPT_RC)
+			erdma_av_to_attr(&qp->attrs.rocev2.av,
+					 &qp_attr->ah_attr);
+	} else {
+		qp_attr->qp_state = query_qp_state(qp);
+		qp_attr->cur_qp_state = qp_attr->qp_state;
+	}
 
 	return 0;
 }
@@ -2095,7 +2127,7 @@ void erdma_attr_to_av(const struct rdma_ah_attr *ah_attr, struct erdma_av *av,
 		av->ntype = ERDMA_NETWORK_TYPE_IPV6;
 }
 
-static void erdma_av_to_attr(struct erdma_av *av, struct rdma_ah_attr *attr)
+void erdma_av_to_attr(struct erdma_av *av, struct rdma_ah_attr *attr)
 {
 	attr->type = RDMA_AH_ATTR_TYPE_ROCE;
 
diff --git a/drivers/infiniband/hw/erdma/erdma_verbs.h b/drivers/infiniband/hw/erdma/erdma_verbs.h
index 5d8cbac76434..4a506b960a44 100644
--- a/drivers/infiniband/hw/erdma/erdma_verbs.h
+++ b/drivers/infiniband/hw/erdma/erdma_verbs.h
@@ -485,6 +485,7 @@ int erdma_del_gid(const struct ib_gid_attr *attr, void **context);
 int erdma_query_pkey(struct ib_device *ibdev, u32 port, u16 index, u16 *pkey);
 void erdma_attr_to_av(const struct rdma_ah_attr *ah_attr, struct erdma_av *av,
 		      u16 sport);
+void erdma_av_to_attr(struct erdma_av *av, struct rdma_ah_attr *attr);
 void erdma_set_av_cfg(struct erdma_av_cfg *av_cfg, struct erdma_av *av);
 int erdma_create_ah(struct ib_ah *ibah, struct rdma_ah_init_attr *init_attr,
 		    struct ib_udata *udata);
-- 
2.43.5


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH for-next 8/8] RDMA/erdma: Support UD QPs and UD WRs
  2024-11-26  6:59 [PATCH for-next 0/8] RDMA/erdma: Support the RoCEv2 protocol Boshi Yu
                   ` (6 preceding siblings ...)
  2024-11-26  6:59 ` [PATCH for-next 7/8] RDMA/erdma: Add the query_qp command to the cmdq Boshi Yu
@ 2024-11-26  6:59 ` Boshi Yu
  7 siblings, 0 replies; 21+ messages in thread
From: Boshi Yu @ 2024-11-26  6:59 UTC (permalink / raw)
  To: jgg, leon; +Cc: linux-rdma, kaishen, chengyou

The iWARP protocol supports only RC QPs previously. Now we add UD QPs
and UD WRs support for the RoCEv2 protocol.

Signed-off-by: Boshi Yu <boshiyu@linux.alibaba.com>
Reviewed-by: Cheng Xu <chengyou@linux.alibaba.com>
---
 drivers/infiniband/hw/erdma/erdma_cq.c    | 20 +++++++
 drivers/infiniband/hw/erdma/erdma_hw.h    | 37 +++++++++++-
 drivers/infiniband/hw/erdma/erdma_qp.c    | 71 ++++++++++++++++++-----
 drivers/infiniband/hw/erdma/erdma_verbs.c | 29 +++++++--
 4 files changed, 136 insertions(+), 21 deletions(-)

diff --git a/drivers/infiniband/hw/erdma/erdma_cq.c b/drivers/infiniband/hw/erdma/erdma_cq.c
index eada882472a3..1f456327e63c 100644
--- a/drivers/infiniband/hw/erdma/erdma_cq.c
+++ b/drivers/infiniband/hw/erdma/erdma_cq.c
@@ -105,6 +105,22 @@ static const struct {
 	{ ERDMA_WC_RETRY_EXC_ERR, IB_WC_RETRY_EXC_ERR, ERDMA_WC_VENDOR_NO_ERR },
 };
 
+static void erdma_process_ud_cqe(struct erdma_cqe *cqe, struct ib_wc *wc)
+{
+	u32 ud_info;
+
+	wc->wc_flags |= (IB_WC_GRH | IB_WC_WITH_NETWORK_HDR_TYPE);
+	ud_info = be32_to_cpu(cqe->ud.info);
+	wc->network_hdr_type = FIELD_GET(ERDMA_CQE_NTYPE_MASK, ud_info);
+	if (wc->network_hdr_type == ERDMA_NETWORK_TYPE_IPV4)
+		wc->network_hdr_type = RDMA_NETWORK_IPV4;
+	else
+		wc->network_hdr_type = RDMA_NETWORK_IPV6;
+	wc->src_qp = FIELD_GET(ERDMA_CQE_SQPN_MASK, ud_info);
+	wc->sl = FIELD_GET(ERDMA_CQE_SL_MASK, ud_info);
+	wc->pkey_index = 0;
+}
+
 #define ERDMA_POLLCQ_NO_QP 1
 
 static int erdma_poll_one_cqe(struct erdma_cq *cq, struct ib_wc *wc)
@@ -168,6 +184,10 @@ static int erdma_poll_one_cqe(struct erdma_cq *cq, struct ib_wc *wc)
 		wc->wc_flags |= IB_WC_WITH_INVALIDATE;
 	}
 
+	if (erdma_device_rocev2(dev) &&
+	    (qp->ibqp.qp_type == IB_QPT_UD || qp->ibqp.qp_type == IB_QPT_GSI))
+		erdma_process_ud_cqe(cqe, wc);
+
 	if (syndrome >= ERDMA_NUM_WC_STATUS)
 		syndrome = ERDMA_WC_GENERAL_ERR;
 
diff --git a/drivers/infiniband/hw/erdma/erdma_hw.h b/drivers/infiniband/hw/erdma/erdma_hw.h
index 809e77dde271..ea4db53901a4 100644
--- a/drivers/infiniband/hw/erdma/erdma_hw.h
+++ b/drivers/infiniband/hw/erdma/erdma_hw.h
@@ -374,6 +374,11 @@ struct erdma_cmdq_query_qp_req_rocev2 {
 	u32 qpn;
 };
 
+enum erdma_qp_type {
+	ERDMA_QPT_RC = 0,
+	ERDMA_QPT_UD = 1,
+};
+
 /* create qp cfg0 */
 #define ERDMA_CMD_CREATE_QP_SQ_DEPTH_MASK GENMASK(31, 20)
 #define ERDMA_CMD_CREATE_QP_QPN_MASK GENMASK(19, 0)
@@ -382,6 +387,9 @@ struct erdma_cmdq_query_qp_req_rocev2 {
 #define ERDMA_CMD_CREATE_QP_RQ_DEPTH_MASK GENMASK(31, 20)
 #define ERDMA_CMD_CREATE_QP_PD_MASK GENMASK(19, 0)
 
+/* create qp cfg2 */
+#define ERDMA_CMD_CREATE_QP_TYPE_MASK GENMASK(3, 0)
+
 /* create qp cqn_mtt_cfg */
 #define ERDMA_CMD_CREATE_QP_PAGE_SIZE_MASK GENMASK(31, 28)
 #define ERDMA_CMD_CREATE_QP_DB_CFG_MASK BIT(25)
@@ -415,6 +423,7 @@ struct erdma_cmdq_create_qp_req {
 	u64 rq_mtt_entry[3];
 
 	u32 db_cfg;
+	u32 cfg2;
 };
 
 struct erdma_cmdq_destroy_qp_req {
@@ -522,6 +531,10 @@ enum {
 #define ERDMA_CQE_QTYPE_RQ 1
 #define ERDMA_CQE_QTYPE_CMDQ 2
 
+#define ERDMA_CQE_NTYPE_MASK BIT(31)
+#define ERDMA_CQE_SL_MASK GENMASK(27, 20)
+#define ERDMA_CQE_SQPN_MASK GENMASK(19, 0)
+
 struct erdma_cqe {
 	__be32 hdr;
 	__be32 qe_idx;
@@ -531,7 +544,16 @@ struct erdma_cqe {
 		__be32 inv_rkey;
 	};
 	__be32 size;
-	__be32 rsvd[3];
+	union {
+		struct {
+			__be32 rsvd[3];
+		} rc;
+
+		struct {
+			__be32 rsvd[2];
+			__be32 info;
+		} ud;
+	};
 };
 
 struct erdma_sge {
@@ -583,7 +605,7 @@ struct erdma_write_sqe {
 	struct erdma_sge sgl[];
 };
 
-struct erdma_send_sqe {
+struct erdma_send_sqe_rc {
 	__le64 hdr;
 	union {
 		__be32 imm_data;
@@ -594,6 +616,17 @@ struct erdma_send_sqe {
 	struct erdma_sge sgl[];
 };
 
+struct erdma_send_sqe_ud {
+	__le64 hdr;
+	__be32 imm_data;
+	__le32 length;
+	__le32 qkey;
+	__le32 dst_qpn;
+	__le32 ahn;
+	__le32 rsvd;
+	struct erdma_sge sgl[];
+};
+
 struct erdma_readreq_sqe {
 	__le64 hdr;
 	__le32 invalid_stag;
diff --git a/drivers/infiniband/hw/erdma/erdma_qp.c b/drivers/infiniband/hw/erdma/erdma_qp.c
index 03d93f026fca..4dfb4272ad86 100644
--- a/drivers/infiniband/hw/erdma/erdma_qp.c
+++ b/drivers/infiniband/hw/erdma/erdma_qp.c
@@ -398,17 +398,57 @@ static int fill_sgl(struct erdma_qp *qp, const struct ib_send_wr *send_wr,
 	return 0;
 }
 
+static void init_send_sqe_rc(struct erdma_qp *qp, struct erdma_send_sqe_rc *sqe,
+			     const struct ib_send_wr *wr, u32 *hw_op)
+{
+	u32 op = ERDMA_OP_SEND;
+
+	if (wr->opcode == IB_WR_SEND_WITH_IMM) {
+		op = ERDMA_OP_SEND_WITH_IMM;
+		sqe->imm_data = wr->ex.imm_data;
+	} else if (op == IB_WR_SEND_WITH_INV) {
+		op = ERDMA_OP_SEND_WITH_INV;
+		sqe->invalid_stag = cpu_to_le32(wr->ex.invalidate_rkey);
+	}
+
+	*hw_op = op;
+}
+
+static void init_send_sqe_ud(struct erdma_qp *qp, struct erdma_send_sqe_ud *sqe,
+			     const struct ib_send_wr *wr, u32 *hw_op)
+{
+	const struct ib_ud_wr *uwr = ud_wr(wr);
+	struct erdma_ah *ah = to_eah(uwr->ah);
+	u32 op = ERDMA_OP_SEND;
+
+	if (wr->opcode == IB_WR_SEND_WITH_IMM) {
+		op = ERDMA_OP_SEND_WITH_IMM;
+		sqe->imm_data = wr->ex.imm_data;
+	}
+
+	*hw_op = op;
+
+	sqe->ahn = cpu_to_le32(ah->ahn);
+	sqe->dst_qpn = cpu_to_le32(uwr->remote_qpn);
+	/* Not allowed to send control qkey */
+	if (uwr->remote_qkey & 0x80000000)
+		sqe->qkey = cpu_to_le32(qp->attrs.rocev2.qkey);
+	else
+		sqe->qkey = cpu_to_le32(uwr->remote_qkey);
+}
+
 static int erdma_push_one_sqe(struct erdma_qp *qp, u16 *pi,
 			      const struct ib_send_wr *send_wr)
 {
 	u32 wqe_size, wqebb_cnt, hw_op, flags, sgl_offset;
 	u32 idx = *pi & (qp->attrs.sq_size - 1);
 	enum ib_wr_opcode op = send_wr->opcode;
+	struct erdma_send_sqe_rc *rc_send_sqe;
+	struct erdma_send_sqe_ud *ud_send_sqe;
 	struct erdma_atomic_sqe *atomic_sqe;
 	struct erdma_readreq_sqe *read_sqe;
 	struct erdma_reg_mr_sqe *regmr_sge;
 	struct erdma_write_sqe *write_sqe;
-	struct erdma_send_sqe *send_sqe;
 	struct ib_rdma_wr *rdma_wr;
 	struct erdma_sge *sge;
 	__le32 *length_field;
@@ -417,6 +457,10 @@ static int erdma_push_one_sqe(struct erdma_qp *qp, u16 *pi,
 	u32 attrs;
 	int ret;
 
+	if (qp->ibqp.qp_type != IB_QPT_RC && send_wr->opcode != IB_WR_SEND &&
+	    send_wr->opcode != IB_WR_SEND_WITH_IMM)
+		return -EINVAL;
+
 	entry = get_queue_entry(qp->kern_qp.sq_buf, idx, qp->attrs.sq_size,
 				SQEBB_SHIFT);
 
@@ -490,21 +534,20 @@ static int erdma_push_one_sqe(struct erdma_qp *qp, u16 *pi,
 	case IB_WR_SEND:
 	case IB_WR_SEND_WITH_IMM:
 	case IB_WR_SEND_WITH_INV:
-		send_sqe = (struct erdma_send_sqe *)entry;
-		hw_op = ERDMA_OP_SEND;
-		if (op == IB_WR_SEND_WITH_IMM) {
-			hw_op = ERDMA_OP_SEND_WITH_IMM;
-			send_sqe->imm_data = send_wr->ex.imm_data;
-		} else if (op == IB_WR_SEND_WITH_INV) {
-			hw_op = ERDMA_OP_SEND_WITH_INV;
-			send_sqe->invalid_stag =
-				cpu_to_le32(send_wr->ex.invalidate_rkey);
+		if (qp->ibqp.qp_type == IB_QPT_RC) {
+			rc_send_sqe = (struct erdma_send_sqe_rc *)entry;
+			init_send_sqe_rc(qp, rc_send_sqe, send_wr, &hw_op);
+			length_field = &rc_send_sqe->length;
+			wqe_size = sizeof(struct erdma_send_sqe_rc);
+		} else {
+			ud_send_sqe = (struct erdma_send_sqe_ud *)entry;
+			init_send_sqe_ud(qp, ud_send_sqe, send_wr, &hw_op);
+			length_field = &ud_send_sqe->length;
+			wqe_size = sizeof(struct erdma_send_sqe_ud);
 		}
-		wqe_hdr |= FIELD_PREP(ERDMA_SQE_HDR_OPCODE_MASK, hw_op);
-		length_field = &send_sqe->length;
-		wqe_size = sizeof(struct erdma_send_sqe);
-		sgl_offset = wqe_size;
 
+		sgl_offset = wqe_size;
+		wqe_hdr |= FIELD_PREP(ERDMA_SQE_HDR_OPCODE_MASK, hw_op);
 		break;
 	case IB_WR_REG_MR:
 		wqe_hdr |=
diff --git a/drivers/infiniband/hw/erdma/erdma_verbs.c b/drivers/infiniband/hw/erdma/erdma_verbs.c
index 28b792c31059..17850eea4938 100644
--- a/drivers/infiniband/hw/erdma/erdma_verbs.c
+++ b/drivers/infiniband/hw/erdma/erdma_verbs.c
@@ -55,6 +55,13 @@ static int create_qp_cmd(struct erdma_ucontext *uctx, struct erdma_qp *qp)
 			      ilog2(qp->attrs.rq_size)) |
 		   FIELD_PREP(ERDMA_CMD_CREATE_QP_PD_MASK, pd->pdn);
 
+	if (qp->ibqp.qp_type == IB_QPT_RC)
+		req.cfg2 = FIELD_PREP(ERDMA_CMD_CREATE_QP_TYPE_MASK,
+				      ERDMA_QPT_RC);
+	else
+		req.cfg2 = FIELD_PREP(ERDMA_CMD_CREATE_QP_TYPE_MASK,
+				      ERDMA_QPT_UD);
+
 	if (rdma_is_kernel_res(&qp->ibqp.res)) {
 		u32 pgsz_range = ilog2(SZ_1M) - ERDMA_HW_PAGE_SHIFT;
 
@@ -481,7 +488,11 @@ static int erdma_qp_validate_cap(struct erdma_dev *dev,
 static int erdma_qp_validate_attr(struct erdma_dev *dev,
 				  struct ib_qp_init_attr *attrs)
 {
-	if (attrs->qp_type != IB_QPT_RC)
+	if (erdma_device_iwarp(dev) && attrs->qp_type != IB_QPT_RC)
+		return -EOPNOTSUPP;
+
+	if (erdma_device_rocev2(dev) && attrs->qp_type != IB_QPT_RC &&
+	    attrs->qp_type != IB_QPT_UD && attrs->qp_type != IB_QPT_GSI)
 		return -EOPNOTSUPP;
 
 	if (attrs->srq)
@@ -959,7 +970,8 @@ int erdma_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs,
 		udata, struct erdma_ucontext, ibucontext);
 	struct erdma_ureq_create_qp ureq;
 	struct erdma_uresp_create_qp uresp;
-	int ret;
+	void *old_entry;
+	int ret = 0;
 
 	ret = erdma_qp_validate_cap(dev, attrs);
 	if (ret)
@@ -978,9 +990,16 @@ int erdma_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs,
 	kref_init(&qp->ref);
 	init_completion(&qp->safe_free);
 
-	ret = xa_alloc_cyclic(&dev->qp_xa, &qp->ibqp.qp_num, qp,
-			      XA_LIMIT(1, dev->attrs.max_qp - 1),
-			      &dev->next_alloc_qpn, GFP_KERNEL);
+	if (qp->ibqp.qp_type == IB_QPT_GSI) {
+		old_entry = xa_store(&dev->qp_xa, 1, qp, GFP_KERNEL);
+		if (xa_is_err(old_entry))
+			ret = xa_err(old_entry);
+	} else {
+		ret = xa_alloc_cyclic(&dev->qp_xa, &qp->ibqp.qp_num, qp,
+				      XA_LIMIT(1, dev->attrs.max_qp - 1),
+				      &dev->next_alloc_qpn, GFP_KERNEL);
+	}
+
 	if (ret < 0) {
 		ret = -ENOMEM;
 		goto err_out;
-- 
2.43.5


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* Re: [PATCH for-next 1/8] RDMA/erdma: Probe the erdma RoCEv2 device
  2024-11-26  6:59 ` [PATCH for-next 1/8] RDMA/erdma: Probe the erdma RoCEv2 device Boshi Yu
@ 2024-11-26 15:36   ` Zhu Yanjun
  2024-11-28  2:07     ` Cheng Xu
  2024-12-04 14:03   ` Leon Romanovsky
  1 sibling, 1 reply; 21+ messages in thread
From: Zhu Yanjun @ 2024-11-26 15:36 UTC (permalink / raw)
  To: Boshi Yu, jgg, leon; +Cc: linux-rdma, kaishen, chengyou

在 2024/11/26 7:59, Boshi Yu 写道:
> Currently, the erdma driver supports both the iWARP and RoCEv2 protocols.
> The erdma driver reads the ERDMA_REGS_DEV_PROTO_REG register to identify
> the protocol used by the erdma device. Since each protocol requires
> different ib_device_ops, we introduce the erdma_device_ops_iwarp and
> erdma_device_ops_rocev2 for iWARP and RoCEv2 protocols, respectively.
> 
Hi, Boshi

 From alomost all of the RDMA users, it seems that RoCEv2 protocol is 
required while very few users request iWARP protocol in their production 
hosts. But in the erdma HW/FW, this iWARP protocol is supported. Is this 
iWARP protocol for some special use cases in the Ali-Cloud environment?

I am just curious about this, not to be against this patch series. If 
this is related with the Ali-Cloud security, you can ignore this.

Thanks,
Zhu Yanjun

> Signed-off-by: Boshi Yu <boshiyu@linux.alibaba.com>
> Reviewed-by: Cheng Xu <chengyou@linux.alibaba.com>
> ---
>   drivers/infiniband/hw/erdma/Kconfig       |  2 +-
>   drivers/infiniband/hw/erdma/erdma.h       |  3 +-
>   drivers/infiniband/hw/erdma/erdma_hw.h    |  7 ++++
>   drivers/infiniband/hw/erdma/erdma_main.c  | 47 ++++++++++++++++++-----
>   drivers/infiniband/hw/erdma/erdma_verbs.c | 16 +++++++-
>   drivers/infiniband/hw/erdma/erdma_verbs.h | 12 ++++++
>   6 files changed, 75 insertions(+), 12 deletions(-)
> 
> diff --git a/drivers/infiniband/hw/erdma/Kconfig b/drivers/infiniband/hw/erdma/Kconfig
> index 169038e3ceb1..267fc1f3c42a 100644
> --- a/drivers/infiniband/hw/erdma/Kconfig
> +++ b/drivers/infiniband/hw/erdma/Kconfig
> @@ -5,7 +5,7 @@ config INFINIBAND_ERDMA
>   	depends on INFINIBAND_ADDR_TRANS
>   	depends on INFINIBAND_USER_ACCESS
>   	help
> -	  This is a RDMA/iWarp driver for Alibaba Elastic RDMA Adapter(ERDMA),
> +	  This is a RDMA driver for Alibaba Elastic RDMA Adapter(ERDMA),
>   	  which supports RDMA features in Alibaba cloud environment.
>   
>   	  To compile this driver as module, choose M here. The module will be
> diff --git a/drivers/infiniband/hw/erdma/erdma.h b/drivers/infiniband/hw/erdma/erdma.h
> index 3c166359448d..ad4dc1a4bdc7 100644
> --- a/drivers/infiniband/hw/erdma/erdma.h
> +++ b/drivers/infiniband/hw/erdma/erdma.h
> @@ -16,7 +16,7 @@
>   #include "erdma_hw.h"
>   
>   #define DRV_MODULE_NAME "erdma"
> -#define ERDMA_NODE_DESC "Elastic RDMA(iWARP) stack"
> +#define ERDMA_NODE_DESC "Elastic RDMA Adapter stack"
>   
>   struct erdma_eq {
>   	void *qbuf;
> @@ -215,6 +215,7 @@ struct erdma_dev {
>   
>   	struct dma_pool *db_pool;
>   	struct dma_pool *resp_pool;
> +	enum erdma_proto_type proto;
>   };
>   
>   static inline void *get_queue_entry(void *qbuf, u32 idx, u32 depth, u32 shift)
> diff --git a/drivers/infiniband/hw/erdma/erdma_hw.h b/drivers/infiniband/hw/erdma/erdma_hw.h
> index 05978f3b1475..970b392d4fb4 100644
> --- a/drivers/infiniband/hw/erdma/erdma_hw.h
> +++ b/drivers/infiniband/hw/erdma/erdma_hw.h
> @@ -21,8 +21,15 @@
>   #define ERDMA_NUM_MSIX_VEC 32U
>   #define ERDMA_MSIX_VECTOR_CMDQ 0
>   
> +/* erdma device protocol type */
> +enum erdma_proto_type {
> +	ERDMA_PROTO_IWARP = 0,
> +	ERDMA_PROTO_ROCEV2 = 1,
> +};
> +
>   /* PCIe Bar0 Registers. */
>   #define ERDMA_REGS_VERSION_REG 0x0
> +#define ERDMA_REGS_DEV_PROTO_REG 0xC
>   #define ERDMA_REGS_DEV_CTRL_REG 0x10
>   #define ERDMA_REGS_DEV_ST_REG 0x14
>   #define ERDMA_REGS_NETDEV_MAC_L_REG 0x18
> diff --git a/drivers/infiniband/hw/erdma/erdma_main.c b/drivers/infiniband/hw/erdma/erdma_main.c
> index 62f497a71004..b6706c74cd96 100644
> --- a/drivers/infiniband/hw/erdma/erdma_main.c
> +++ b/drivers/infiniband/hw/erdma/erdma_main.c
> @@ -172,6 +172,12 @@ static int erdma_device_init(struct erdma_dev *dev, struct pci_dev *pdev)
>   {
>   	int ret;
>   
> +	dev->proto = erdma_reg_read32(dev, ERDMA_REGS_DEV_PROTO_REG);
> +	if (!erdma_device_iwarp(dev) && !erdma_device_rocev2(dev)) {
> +		dev_err(&pdev->dev, "Unsupported protocol: %d\n", dev->proto);
> +		return -ENODEV;
> +	}
> +
>   	dev->resp_pool = dma_pool_create("erdma_resp_pool", &pdev->dev,
>   					 ERDMA_HW_RESP_SIZE, ERDMA_HW_RESP_SIZE,
>   					 0);
> @@ -474,6 +480,21 @@ static void erdma_res_cb_free(struct erdma_dev *dev)
>   		bitmap_free(dev->res_cb[i].bitmap);
>   }
>   
> +static const struct ib_device_ops erdma_device_ops_rocev2 = {
> +	.get_link_layer = erdma_get_link_layer,
> +};
> +
> +static const struct ib_device_ops erdma_device_ops_iwarp = {
> +	.iw_accept = erdma_accept,
> +	.iw_add_ref = erdma_qp_get_ref,
> +	.iw_connect = erdma_connect,
> +	.iw_create_listen = erdma_create_listen,
> +	.iw_destroy_listen = erdma_destroy_listen,
> +	.iw_get_qp = erdma_get_ibqp,
> +	.iw_reject = erdma_reject,
> +	.iw_rem_ref = erdma_qp_put_ref,
> +};
> +
>   static const struct ib_device_ops erdma_device_ops = {
>   	.owner = THIS_MODULE,
>   	.driver_id = RDMA_DRIVER_ERDMA,
> @@ -494,14 +515,6 @@ static const struct ib_device_ops erdma_device_ops = {
>   	.get_dma_mr = erdma_get_dma_mr,
>   	.get_hw_stats = erdma_get_hw_stats,
>   	.get_port_immutable = erdma_get_port_immutable,
> -	.iw_accept = erdma_accept,
> -	.iw_add_ref = erdma_qp_get_ref,
> -	.iw_connect = erdma_connect,
> -	.iw_create_listen = erdma_create_listen,
> -	.iw_destroy_listen = erdma_destroy_listen,
> -	.iw_get_qp = erdma_get_ibqp,
> -	.iw_reject = erdma_reject,
> -	.iw_rem_ref = erdma_qp_put_ref,
>   	.map_mr_sg = erdma_map_mr_sg,
>   	.mmap = erdma_mmap,
>   	.mmap_free = erdma_mmap_free,
> @@ -522,6 +535,18 @@ static const struct ib_device_ops erdma_device_ops = {
>   	INIT_RDMA_OBJ_SIZE(ib_qp, erdma_qp, ibqp),
>   };
>   
> +static void erdma_device_init_iwarp(struct ib_device *ibdev)
> +{
> +	ibdev->node_type = RDMA_NODE_RNIC;
> +	ib_set_device_ops(ibdev, &erdma_device_ops_iwarp);
> +}
> +
> +static void erdma_device_init_rocev2(struct ib_device *ibdev)
> +{
> +	ibdev->node_type = RDMA_NODE_IB_CA;
> +	ib_set_device_ops(ibdev, &erdma_device_ops_rocev2);
> +}
> +
>   static int erdma_ib_device_add(struct pci_dev *pdev)
>   {
>   	struct erdma_dev *dev = pci_get_drvdata(pdev);
> @@ -537,7 +562,11 @@ static int erdma_ib_device_add(struct pci_dev *pdev)
>   	if (ret)
>   		return ret;
>   
> -	ibdev->node_type = RDMA_NODE_RNIC;
> +	if (erdma_device_iwarp(dev))
> +		erdma_device_init_iwarp(&dev->ibdev);
> +	else
> +		erdma_device_init_rocev2(&dev->ibdev);
> +
>   	memcpy(ibdev->node_desc, ERDMA_NODE_DESC, sizeof(ERDMA_NODE_DESC));
>   
>   	/*
> diff --git a/drivers/infiniband/hw/erdma/erdma_verbs.c b/drivers/infiniband/hw/erdma/erdma_verbs.c
> index 51d619edb6c5..3b7e55515cfd 100644
> --- a/drivers/infiniband/hw/erdma/erdma_verbs.c
> +++ b/drivers/infiniband/hw/erdma/erdma_verbs.c
> @@ -395,8 +395,17 @@ int erdma_query_port(struct ib_device *ibdev, u32 port,
>   int erdma_get_port_immutable(struct ib_device *ibdev, u32 port,
>   			     struct ib_port_immutable *port_immutable)
>   {
> +	struct erdma_dev *dev = to_edev(ibdev);
> +
> +	if (erdma_device_iwarp(dev)) {
> +		port_immutable->core_cap_flags = RDMA_CORE_PORT_IWARP;
> +	} else {
> +		port_immutable->core_cap_flags =
> +			RDMA_CORE_PORT_IBA_ROCE_UDP_ENCAP;
> +		port_immutable->max_mad_size = IB_MGMT_MAD_SIZE;
> +	}
> +
>   	port_immutable->gid_tbl_len = 1;
> -	port_immutable->core_cap_flags = RDMA_CORE_PORT_IWARP;
>   
>   	return 0;
>   }
> @@ -1839,3 +1848,8 @@ int erdma_get_hw_stats(struct ib_device *ibdev, struct rdma_hw_stats *stats,
>   
>   	return stats->num_counters;
>   }
> +
> +enum rdma_link_layer erdma_get_link_layer(struct ib_device *ibdev, u32 port_num)
> +{
> +	return IB_LINK_LAYER_ETHERNET;
> +}
> diff --git a/drivers/infiniband/hw/erdma/erdma_verbs.h b/drivers/infiniband/hw/erdma/erdma_verbs.h
> index c998acd39a78..90e2b35a0973 100644
> --- a/drivers/infiniband/hw/erdma/erdma_verbs.h
> +++ b/drivers/infiniband/hw/erdma/erdma_verbs.h
> @@ -291,6 +291,16 @@ int erdma_modify_qp_internal(struct erdma_qp *qp, struct erdma_qp_attrs *attrs,
>   void erdma_qp_llp_close(struct erdma_qp *qp);
>   void erdma_qp_cm_drop(struct erdma_qp *qp);
>   
> +static inline bool erdma_device_iwarp(struct erdma_dev *dev)
> +{
> +	return dev->proto == ERDMA_PROTO_IWARP;
> +}
> +
> +static inline bool erdma_device_rocev2(struct erdma_dev *dev)
> +{
> +	return dev->proto == ERDMA_PROTO_ROCEV2;
> +}
> +
>   static inline struct erdma_ucontext *to_ectx(struct ib_ucontext *ibctx)
>   {
>   	return container_of(ibctx, struct erdma_ucontext, ibucontext);
> @@ -370,5 +380,7 @@ struct rdma_hw_stats *erdma_alloc_hw_port_stats(struct ib_device *device,
>   						u32 port_num);
>   int erdma_get_hw_stats(struct ib_device *ibdev, struct rdma_hw_stats *stats,
>   		       u32 port, int index);
> +enum rdma_link_layer erdma_get_link_layer(struct ib_device *ibdev,
> +					  u32 port_num);
>   
>   #endif


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH for-next 2/8] RDMA/erdma: Add GID table management interfaces
  2024-11-26  6:59 ` [PATCH for-next 2/8] RDMA/erdma: Add GID table management interfaces Boshi Yu
@ 2024-11-26 15:51   ` Zhu Yanjun
  2024-11-28  2:35     ` Boshi Yu
  0 siblings, 1 reply; 21+ messages in thread
From: Zhu Yanjun @ 2024-11-26 15:51 UTC (permalink / raw)
  To: Boshi Yu, jgg, leon; +Cc: linux-rdma, kaishen, chengyou

在 2024/11/26 7:59, Boshi Yu 写道:
> The erdma_add_gid() interface inserts a GID entry at the
> specified index. The erdma_del_gid() interface deletes the
> GID entry at the specified index. Additionally, programs
> can invoke the erdma_query_port() and erdma_get_port_immutable()
> interfaces to query the GID table length.
> 
> Signed-off-by: Boshi Yu <boshiyu@linux.alibaba.com>
> Reviewed-by: Cheng Xu <chengyou@linux.alibaba.com>
> ---
>   drivers/infiniband/hw/erdma/erdma.h       |  1 +
>   drivers/infiniband/hw/erdma/erdma_hw.h    | 28 +++++++++++-
>   drivers/infiniband/hw/erdma/erdma_main.c  |  3 ++
>   drivers/infiniband/hw/erdma/erdma_verbs.c | 56 +++++++++++++++++++++--
>   drivers/infiniband/hw/erdma/erdma_verbs.h | 12 +++++
>   5 files changed, 96 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/infiniband/hw/erdma/erdma.h b/drivers/infiniband/hw/erdma/erdma.h
> index ad4dc1a4bdc7..42dabf674f5d 100644
> --- a/drivers/infiniband/hw/erdma/erdma.h
> +++ b/drivers/infiniband/hw/erdma/erdma.h
> @@ -148,6 +148,7 @@ struct erdma_devattr {
>   	u32 max_mr;
>   	u32 max_pd;
>   	u32 max_mw;
> +	u32 max_gid;
>   	u32 local_dma_key;
>   };
>   
> diff --git a/drivers/infiniband/hw/erdma/erdma_hw.h b/drivers/infiniband/hw/erdma/erdma_hw.h
> index 970b392d4fb4..7e03c5f97501 100644
> --- a/drivers/infiniband/hw/erdma/erdma_hw.h
> +++ b/drivers/infiniband/hw/erdma/erdma_hw.h
> @@ -21,6 +21,9 @@
>   #define ERDMA_NUM_MSIX_VEC 32U
>   #define ERDMA_MSIX_VECTOR_CMDQ 0
>   
> +/* RoCEv2 related */
> +#define ERDMA_ROCEV2_GID_SIZE 16
> +
>   /* erdma device protocol type */
>   enum erdma_proto_type {
>   	ERDMA_PROTO_IWARP = 0,
> @@ -143,7 +146,8 @@ enum CMDQ_RDMA_OPCODE {
>   	CMDQ_OPCODE_DESTROY_CQ = 5,
>   	CMDQ_OPCODE_REFLUSH = 6,
>   	CMDQ_OPCODE_REG_MR = 8,
> -	CMDQ_OPCODE_DEREG_MR = 9
> +	CMDQ_OPCODE_DEREG_MR = 9,
> +	CMDQ_OPCODE_SET_GID = 14,
>   };
>   
>   enum CMDQ_COMMON_OPCODE {
> @@ -401,7 +405,29 @@ struct erdma_cmdq_query_stats_resp {
>   	u64 rx_pps_meter_drop_packets_cnt;
>   };
>   
> +enum erdma_network_type {
> +	ERDMA_NETWORK_TYPE_IPV4 = 0,
> +	ERDMA_NETWORK_TYPE_IPV6 = 1,
> +};

In the file include/rdma/ib_verbs.h

"
...
  183 enum rdma_network_type {
...
  186     RDMA_NETWORK_IPV4,
  187     RDMA_NETWORK_IPV6
  188 };
...
"
Not sure why the above RDMA_NETWORK_IPV4 and RDMA_NETWORK_IPV6 are not used.

Zhu Yanjun

> +
> +enum erdma_set_gid_op {
> +	ERDMA_SET_GID_OP_ADD = 0,
> +	ERDMA_SET_GID_OP_DEL = 1,
> +};
> +
> +/* set gid cfg */
> +#define ERDMA_CMD_SET_GID_SGID_IDX_MASK GENMASK(15, 0)
> +#define ERDMA_CMD_SET_GID_NTYPE_MASK BIT(16)
> +#define ERDMA_CMD_SET_GID_OP_MASK BIT(31)
> +
> +struct erdma_cmdq_set_gid_req {
> +	u64 hdr;
> +	u32 cfg;
> +	u8 gid[ERDMA_ROCEV2_GID_SIZE];
> +};
> +
>   /* cap qword 0 definition */
> +#define ERDMA_CMD_DEV_CAP_MAX_GID_MASK GENMASK_ULL(51, 48)
>   #define ERDMA_CMD_DEV_CAP_MAX_CQE_MASK GENMASK_ULL(47, 40)
>   #define ERDMA_CMD_DEV_CAP_FLAGS_MASK GENMASK_ULL(31, 24)
>   #define ERDMA_CMD_DEV_CAP_MAX_RECV_WR_MASK GENMASK_ULL(23, 16)
> diff --git a/drivers/infiniband/hw/erdma/erdma_main.c b/drivers/infiniband/hw/erdma/erdma_main.c
> index b6706c74cd96..d72b85e8971d 100644
> --- a/drivers/infiniband/hw/erdma/erdma_main.c
> +++ b/drivers/infiniband/hw/erdma/erdma_main.c
> @@ -404,6 +404,7 @@ static int erdma_dev_attrs_init(struct erdma_dev *dev)
>   	dev->attrs.max_mr_size = 1ULL << ERDMA_GET_CAP(MAX_MR_SIZE, cap0);
>   	dev->attrs.max_mw = 1 << ERDMA_GET_CAP(MAX_MW, cap1);
>   	dev->attrs.max_recv_wr = 1 << ERDMA_GET_CAP(MAX_RECV_WR, cap0);
> +	dev->attrs.max_gid = 1 << ERDMA_GET_CAP(MAX_GID, cap0);
>   	dev->attrs.local_dma_key = ERDMA_GET_CAP(DMA_LOCAL_KEY, cap1);
>   	dev->attrs.cc = ERDMA_GET_CAP(DEFAULT_CC, cap1);
>   	dev->attrs.max_qp = ERDMA_NQP_PER_QBLOCK * ERDMA_GET_CAP(QBLOCK, cap1);
> @@ -482,6 +483,8 @@ static void erdma_res_cb_free(struct erdma_dev *dev)
>   
>   static const struct ib_device_ops erdma_device_ops_rocev2 = {
>   	.get_link_layer = erdma_get_link_layer,
> +	.add_gid = erdma_add_gid,
> +	.del_gid = erdma_del_gid,
>   };
>   
>   static const struct ib_device_ops erdma_device_ops_iwarp = {
> diff --git a/drivers/infiniband/hw/erdma/erdma_verbs.c b/drivers/infiniband/hw/erdma/erdma_verbs.c
> index 3b7e55515cfd..9944eed584ec 100644
> --- a/drivers/infiniband/hw/erdma/erdma_verbs.c
> +++ b/drivers/infiniband/hw/erdma/erdma_verbs.c
> @@ -367,7 +367,13 @@ int erdma_query_port(struct ib_device *ibdev, u32 port,
>   
>   	memset(attr, 0, sizeof(*attr));
>   
> -	attr->gid_tbl_len = 1;
> +	if (erdma_device_iwarp(dev)) {
> +		attr->gid_tbl_len = 1;
> +	} else {
> +		attr->gid_tbl_len = dev->attrs.max_gid;
> +		attr->ip_gids = true;
> +	}
> +
>   	attr->port_cap_flags = IB_PORT_CM_SUP | IB_PORT_DEVICE_MGMT_SUP;
>   	attr->max_msg_sz = -1;
>   
> @@ -399,14 +405,14 @@ int erdma_get_port_immutable(struct ib_device *ibdev, u32 port,
>   
>   	if (erdma_device_iwarp(dev)) {
>   		port_immutable->core_cap_flags = RDMA_CORE_PORT_IWARP;
> +		port_immutable->gid_tbl_len = 1;
>   	} else {
>   		port_immutable->core_cap_flags =
>   			RDMA_CORE_PORT_IBA_ROCE_UDP_ENCAP;
>   		port_immutable->max_mad_size = IB_MGMT_MAD_SIZE;
> +		port_immutable->gid_tbl_len = dev->attrs.max_gid;
>   	}
>   
> -	port_immutable->gid_tbl_len = 1;
> -
>   	return 0;
>   }
>   
> @@ -1853,3 +1859,47 @@ enum rdma_link_layer erdma_get_link_layer(struct ib_device *ibdev, u32 port_num)
>   {
>   	return IB_LINK_LAYER_ETHERNET;
>   }
> +
> +static int erdma_set_gid(struct erdma_dev *dev, u8 op, u32 idx,
> +			 const union ib_gid *gid)
> +{
> +	struct erdma_cmdq_set_gid_req req;
> +	u8 ntype;
> +
> +	req.cfg = FIELD_PREP(ERDMA_CMD_SET_GID_SGID_IDX_MASK, idx) |
> +		  FIELD_PREP(ERDMA_CMD_SET_GID_OP_MASK, op);
> +
> +	if (op == ERDMA_SET_GID_OP_ADD) {
> +		if (ipv6_addr_v4mapped((struct in6_addr *)gid))
> +			ntype = ERDMA_NETWORK_TYPE_IPV4;
> +		else
> +			ntype = ERDMA_NETWORK_TYPE_IPV6;
> +
> +		req.cfg |= FIELD_PREP(ERDMA_CMD_SET_GID_NTYPE_MASK, ntype);
> +
> +		memcpy(&req.gid, gid, ERDMA_ROCEV2_GID_SIZE);
> +	}
> +
> +	erdma_cmdq_build_reqhdr(&req.hdr, CMDQ_SUBMOD_RDMA,
> +				CMDQ_OPCODE_SET_GID);
> +	return erdma_post_cmd_wait(&dev->cmdq, &req, sizeof(req), NULL, NULL);
> +}
> +
> +int erdma_add_gid(const struct ib_gid_attr *attr, void **context)
> +{
> +	struct erdma_dev *dev = to_edev(attr->device);
> +	int ret;
> +
> +	ret = erdma_check_gid_attr(attr);
> +	if (ret)
> +		return ret;
> +
> +	return erdma_set_gid(dev, ERDMA_SET_GID_OP_ADD, attr->index,
> +			     &attr->gid);
> +}
> +
> +int erdma_del_gid(const struct ib_gid_attr *attr, void **context)
> +{
> +	return erdma_set_gid(to_edev(attr->device), ERDMA_SET_GID_OP_DEL,
> +			     attr->index, NULL);
> +}
> diff --git a/drivers/infiniband/hw/erdma/erdma_verbs.h b/drivers/infiniband/hw/erdma/erdma_verbs.h
> index 90e2b35a0973..23cfeaf79eaa 100644
> --- a/drivers/infiniband/hw/erdma/erdma_verbs.h
> +++ b/drivers/infiniband/hw/erdma/erdma_verbs.h
> @@ -326,6 +326,16 @@ static inline struct erdma_cq *to_ecq(struct ib_cq *ibcq)
>   	return container_of(ibcq, struct erdma_cq, ibcq);
>   }
>   
> +static inline int erdma_check_gid_attr(const struct ib_gid_attr *attr)
> +{
> +	u8 ntype = rdma_gid_attr_network_type(attr);
> +
> +	if (ntype != RDMA_NETWORK_IPV4 && ntype != RDMA_NETWORK_IPV6)
> +		return -EINVAL;
> +
> +	return 0;
> +}
> +
>   static inline struct erdma_user_mmap_entry *
>   to_emmap(struct rdma_user_mmap_entry *ibmmap)
>   {
> @@ -382,5 +392,7 @@ int erdma_get_hw_stats(struct ib_device *ibdev, struct rdma_hw_stats *stats,
>   		       u32 port, int index);
>   enum rdma_link_layer erdma_get_link_layer(struct ib_device *ibdev,
>   					  u32 port_num);
> +int erdma_add_gid(const struct ib_gid_attr *attr, void **context);
> +int erdma_del_gid(const struct ib_gid_attr *attr, void **context);
>   
>   #endif


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH for-next 1/8] RDMA/erdma: Probe the erdma RoCEv2 device
  2024-11-26 15:36   ` Zhu Yanjun
@ 2024-11-28  2:07     ` Cheng Xu
  2024-11-28 13:07       ` Zhu Yanjun
  0 siblings, 1 reply; 21+ messages in thread
From: Cheng Xu @ 2024-11-28  2:07 UTC (permalink / raw)
  To: Zhu Yanjun, Boshi Yu, jgg, leon; +Cc: linux-rdma, kaishen



On 11/26/24 11:36 PM, Zhu Yanjun wrote:
> 在 2024/11/26 7:59, Boshi Yu 写道:
>> Currently, the erdma driver supports both the iWARP and RoCEv2 protocols.
>> The erdma driver reads the ERDMA_REGS_DEV_PROTO_REG register to identify
>> the protocol used by the erdma device. Since each protocol requires
>> different ib_device_ops, we introduce the erdma_device_ops_iwarp and
>> erdma_device_ops_rocev2 for iWARP and RoCEv2 protocols, respectively.
>>
> Hi, Boshi
> 
> From alomost all of the RDMA users, it seems that RoCEv2 protocol is required while very few users request iWARP protocol in their production hosts. But in the erdma HW/FW, this iWARP protocol is supported. Is this iWARP protocol for some special use cases in the Ali-Cloud environment?
> 

Hi, Yanjun,

iWarp & TCP have some good features, such as Tail Loss Probe(TLP), selective ACK and
out-of-order DDP, so that can get better performance in large-scale lossy network. The
current usage scenarios include HPC industrial simulation, redis, PolarDB and big data
in public cloud environment.

Thanks,
Cheng Xu

> I am just curious about this, not to be against this patch series. If this is related with the Ali-Cloud security, you can ignore this.
> 
> Thanks,
> Zhu Yanjun
> 


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH for-next 2/8] RDMA/erdma: Add GID table management interfaces
  2024-11-26 15:51   ` Zhu Yanjun
@ 2024-11-28  2:35     ` Boshi Yu
  2024-11-29  8:54       ` Zhu Yanjun
  0 siblings, 1 reply; 21+ messages in thread
From: Boshi Yu @ 2024-11-28  2:35 UTC (permalink / raw)
  To: Zhu Yanjun, jgg, leon, chengyou; +Cc: linux-rdma, kaishen

On Tue, Nov 26, 2024 at 04:51:02PM +0100, Zhu Yanjun wrote:
> 在 2024/11/26 7:59, Boshi Yu 写道:
> > The erdma_add_gid() interface inserts a GID entry at the
> > specified index. The erdma_del_gid() interface deletes the
> > GID entry at the specified index. Additionally, programs
> > can invoke the erdma_query_port() and erdma_get_port_immutable()
> > interfaces to query the GID table length.
> > 
> > Signed-off-by: Boshi Yu <boshiyu@linux.alibaba.com>
> > Reviewed-by: Cheng Xu <chengyou@linux.alibaba.com>
> > ---
> >   drivers/infiniband/hw/erdma/erdma.h       |  1 +
> >   drivers/infiniband/hw/erdma/erdma_hw.h    | 28 +++++++++++-
> >   drivers/infiniband/hw/erdma/erdma_main.c  |  3 ++
> >   drivers/infiniband/hw/erdma/erdma_verbs.c | 56 +++++++++++++++++++++--
> >   drivers/infiniband/hw/erdma/erdma_verbs.h | 12 +++++
> >   5 files changed, 96 insertions(+), 4 deletions(-)
> > 
> > diff --git a/drivers/infiniband/hw/erdma/erdma.h b/drivers/infiniband/hw/erdma/erdma.h
> > index ad4dc1a4bdc7..42dabf674f5d 100644
> > --- a/drivers/infiniband/hw/erdma/erdma.h
> > +++ b/drivers/infiniband/hw/erdma/erdma.h
> > @@ -148,6 +148,7 @@ struct erdma_devattr {
> >   	u32 max_mr;
> >   	u32 max_pd;
> >   	u32 max_mw;
> > +	u32 max_gid;
> >   	u32 local_dma_key;
> >   };
> > diff --git a/drivers/infiniband/hw/erdma/erdma_hw.h b/drivers/infiniband/hw/erdma/erdma_hw.h
> > index 970b392d4fb4..7e03c5f97501 100644
> > --- a/drivers/infiniband/hw/erdma/erdma_hw.h
> > +++ b/drivers/infiniband/hw/erdma/erdma_hw.h
> > @@ -21,6 +21,9 @@
> >   #define ERDMA_NUM_MSIX_VEC 32U
> >   #define ERDMA_MSIX_VECTOR_CMDQ 0
> > +/* RoCEv2 related */
> > +#define ERDMA_ROCEV2_GID_SIZE 16
> > +
> >   /* erdma device protocol type */
> >   enum erdma_proto_type {
> >   	ERDMA_PROTO_IWARP = 0,
> > @@ -143,7 +146,8 @@ enum CMDQ_RDMA_OPCODE {
> >   	CMDQ_OPCODE_DESTROY_CQ = 5,
> >   	CMDQ_OPCODE_REFLUSH = 6,
> >   	CMDQ_OPCODE_REG_MR = 8,
> > -	CMDQ_OPCODE_DEREG_MR = 9
> > +	CMDQ_OPCODE_DEREG_MR = 9,
> > +	CMDQ_OPCODE_SET_GID = 14,
> >   };
> >   enum CMDQ_COMMON_OPCODE {
> > @@ -401,7 +405,29 @@ struct erdma_cmdq_query_stats_resp {
> >   	u64 rx_pps_meter_drop_packets_cnt;
> >   };
> > +enum erdma_network_type {
> > +	ERDMA_NETWORK_TYPE_IPV4 = 0,
> > +	ERDMA_NETWORK_TYPE_IPV6 = 1,
> > +};
> 
> In the file include/rdma/ib_verbs.h
> 
> "
> ...
>  183 enum rdma_network_type {
> ...
>  186     RDMA_NETWORK_IPV4,
>  187     RDMA_NETWORK_IPV6
>  188 };
> ...
> "
> Not sure why the above RDMA_NETWORK_IPV4 and RDMA_NETWORK_IPV6 are not used.
> 
> Zhu Yanjun
> 

Hi, Yanjun,

Given that the values for RDMA_NETWORK_IPV4 and RDMA_NETWORK_IPV6 are 2 and 3,
respectively, we would need 2 bits to store the network type if we use them
directly. However, since we only need to differentiate between IPv4 and IPv6
for the RoCEv2 protocol, 1 bit is sufficient.

Thanks,
Boshi Yu

> > +
> > +enum erdma_set_gid_op {
> > +	ERDMA_SET_GID_OP_ADD = 0,
> > +	ERDMA_SET_GID_OP_DEL = 1,
> > +};
> > +
> > +/* set gid cfg */
> > +#define ERDMA_CMD_SET_GID_SGID_IDX_MASK GENMASK(15, 0)
> > +#define ERDMA_CMD_SET_GID_NTYPE_MASK BIT(16)
> > +#define ERDMA_CMD_SET_GID_OP_MASK BIT(31)
> > +
> > +struct erdma_cmdq_set_gid_req {
> > +	u64 hdr;
> > +	u32 cfg;
> > +	u8 gid[ERDMA_ROCEV2_GID_SIZE];
> > +};
> > +
> >   /* cap qword 0 definition */
> > +#define ERDMA_CMD_DEV_CAP_MAX_GID_MASK GENMASK_ULL(51, 48)
> >   #define ERDMA_CMD_DEV_CAP_MAX_CQE_MASK GENMASK_ULL(47, 40)
> >   #define ERDMA_CMD_DEV_CAP_FLAGS_MASK GENMASK_ULL(31, 24)
> >   #define ERDMA_CMD_DEV_CAP_MAX_RECV_WR_MASK GENMASK_ULL(23, 16)
> > diff --git a/drivers/infiniband/hw/erdma/erdma_main.c b/drivers/infiniband/hw/erdma/erdma_main.c
> > index b6706c74cd96..d72b85e8971d 100644
> > --- a/drivers/infiniband/hw/erdma/erdma_main.c
> > +++ b/drivers/infiniband/hw/erdma/erdma_main.c
> > @@ -404,6 +404,7 @@ static int erdma_dev_attrs_init(struct erdma_dev *dev)
> >   	dev->attrs.max_mr_size = 1ULL << ERDMA_GET_CAP(MAX_MR_SIZE, cap0);
> >   	dev->attrs.max_mw = 1 << ERDMA_GET_CAP(MAX_MW, cap1);
> >   	dev->attrs.max_recv_wr = 1 << ERDMA_GET_CAP(MAX_RECV_WR, cap0);
> > +	dev->attrs.max_gid = 1 << ERDMA_GET_CAP(MAX_GID, cap0);
> >   	dev->attrs.local_dma_key = ERDMA_GET_CAP(DMA_LOCAL_KEY, cap1);
> >   	dev->attrs.cc = ERDMA_GET_CAP(DEFAULT_CC, cap1);
> >   	dev->attrs.max_qp = ERDMA_NQP_PER_QBLOCK * ERDMA_GET_CAP(QBLOCK, cap1);
> > @@ -482,6 +483,8 @@ static void erdma_res_cb_free(struct erdma_dev *dev)
> >   static const struct ib_device_ops erdma_device_ops_rocev2 = {
> >   	.get_link_layer = erdma_get_link_layer,
> > +	.add_gid = erdma_add_gid,
> > +	.del_gid = erdma_del_gid,
> >   };
> >   static const struct ib_device_ops erdma_device_ops_iwarp = {
> > diff --git a/drivers/infiniband/hw/erdma/erdma_verbs.c b/drivers/infiniband/hw/erdma/erdma_verbs.c
> > index 3b7e55515cfd..9944eed584ec 100644
> > --- a/drivers/infiniband/hw/erdma/erdma_verbs.c
> > +++ b/drivers/infiniband/hw/erdma/erdma_verbs.c
> > @@ -367,7 +367,13 @@ int erdma_query_port(struct ib_device *ibdev, u32 port,
> >   	memset(attr, 0, sizeof(*attr));
> > -	attr->gid_tbl_len = 1;
> > +	if (erdma_device_iwarp(dev)) {
> > +		attr->gid_tbl_len = 1;
> > +	} else {
> > +		attr->gid_tbl_len = dev->attrs.max_gid;
> > +		attr->ip_gids = true;
> > +	}
> > +
> >   	attr->port_cap_flags = IB_PORT_CM_SUP | IB_PORT_DEVICE_MGMT_SUP;
> >   	attr->max_msg_sz = -1;
> > @@ -399,14 +405,14 @@ int erdma_get_port_immutable(struct ib_device *ibdev, u32 port,
> >   	if (erdma_device_iwarp(dev)) {
> >   		port_immutable->core_cap_flags = RDMA_CORE_PORT_IWARP;
> > +		port_immutable->gid_tbl_len = 1;
> >   	} else {
> >   		port_immutable->core_cap_flags =
> >   			RDMA_CORE_PORT_IBA_ROCE_UDP_ENCAP;
> >   		port_immutable->max_mad_size = IB_MGMT_MAD_SIZE;
> > +		port_immutable->gid_tbl_len = dev->attrs.max_gid;
> >   	}
> > -	port_immutable->gid_tbl_len = 1;
> > -
> >   	return 0;
> >   }
> > @@ -1853,3 +1859,47 @@ enum rdma_link_layer erdma_get_link_layer(struct ib_device *ibdev, u32 port_num)
> >   {
> >   	return IB_LINK_LAYER_ETHERNET;
> >   }
> > +
> > +static int erdma_set_gid(struct erdma_dev *dev, u8 op, u32 idx,
> > +			 const union ib_gid *gid)
> > +{
> > +	struct erdma_cmdq_set_gid_req req;
> > +	u8 ntype;
> > +
> > +	req.cfg = FIELD_PREP(ERDMA_CMD_SET_GID_SGID_IDX_MASK, idx) |
> > +		  FIELD_PREP(ERDMA_CMD_SET_GID_OP_MASK, op);
> > +
> > +	if (op == ERDMA_SET_GID_OP_ADD) {
> > +		if (ipv6_addr_v4mapped((struct in6_addr *)gid))
> > +			ntype = ERDMA_NETWORK_TYPE_IPV4;
> > +		else
> > +			ntype = ERDMA_NETWORK_TYPE_IPV6;
> > +
> > +		req.cfg |= FIELD_PREP(ERDMA_CMD_SET_GID_NTYPE_MASK, ntype);
> > +
> > +		memcpy(&req.gid, gid, ERDMA_ROCEV2_GID_SIZE);
> > +	}
> > +
> > +	erdma_cmdq_build_reqhdr(&req.hdr, CMDQ_SUBMOD_RDMA,
> > +				CMDQ_OPCODE_SET_GID);
> > +	return erdma_post_cmd_wait(&dev->cmdq, &req, sizeof(req), NULL, NULL);
> > +}
> > +
> > +int erdma_add_gid(const struct ib_gid_attr *attr, void **context)
> > +{
> > +	struct erdma_dev *dev = to_edev(attr->device);
> > +	int ret;
> > +
> > +	ret = erdma_check_gid_attr(attr);
> > +	if (ret)
> > +		return ret;
> > +
> > +	return erdma_set_gid(dev, ERDMA_SET_GID_OP_ADD, attr->index,
> > +			     &attr->gid);
> > +}
> > +
> > +int erdma_del_gid(const struct ib_gid_attr *attr, void **context)
> > +{
> > +	return erdma_set_gid(to_edev(attr->device), ERDMA_SET_GID_OP_DEL,
> > +			     attr->index, NULL);
> > +}
> > diff --git a/drivers/infiniband/hw/erdma/erdma_verbs.h b/drivers/infiniband/hw/erdma/erdma_verbs.h
> > index 90e2b35a0973..23cfeaf79eaa 100644
> > --- a/drivers/infiniband/hw/erdma/erdma_verbs.h
> > +++ b/drivers/infiniband/hw/erdma/erdma_verbs.h
> > @@ -326,6 +326,16 @@ static inline struct erdma_cq *to_ecq(struct ib_cq *ibcq)
> >   	return container_of(ibcq, struct erdma_cq, ibcq);
> >   }
> > +static inline int erdma_check_gid_attr(const struct ib_gid_attr *attr)
> > +{
> > +	u8 ntype = rdma_gid_attr_network_type(attr);
> > +
> > +	if (ntype != RDMA_NETWORK_IPV4 && ntype != RDMA_NETWORK_IPV6)
> > +		return -EINVAL;
> > +
> > +	return 0;
> > +}
> > +
> >   static inline struct erdma_user_mmap_entry *
> >   to_emmap(struct rdma_user_mmap_entry *ibmmap)
> >   {
> > @@ -382,5 +392,7 @@ int erdma_get_hw_stats(struct ib_device *ibdev, struct rdma_hw_stats *stats,
> >   		       u32 port, int index);
> >   enum rdma_link_layer erdma_get_link_layer(struct ib_device *ibdev,
> >   					  u32 port_num);
> > +int erdma_add_gid(const struct ib_gid_attr *attr, void **context);
> > +int erdma_del_gid(const struct ib_gid_attr *attr, void **context);
> >   #endif

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH for-next 1/8] RDMA/erdma: Probe the erdma RoCEv2 device
  2024-11-28  2:07     ` Cheng Xu
@ 2024-11-28 13:07       ` Zhu Yanjun
  0 siblings, 0 replies; 21+ messages in thread
From: Zhu Yanjun @ 2024-11-28 13:07 UTC (permalink / raw)
  To: Cheng Xu, Boshi Yu, jgg, leon; +Cc: linux-rdma, kaishen

在 2024/11/28 3:07, Cheng Xu 写道:
> 
> 
> On 11/26/24 11:36 PM, Zhu Yanjun wrote:
>> 在 2024/11/26 7:59, Boshi Yu 写道:
>>> Currently, the erdma driver supports both the iWARP and RoCEv2 protocols.
>>> The erdma driver reads the ERDMA_REGS_DEV_PROTO_REG register to identify
>>> the protocol used by the erdma device. Since each protocol requires
>>> different ib_device_ops, we introduce the erdma_device_ops_iwarp and
>>> erdma_device_ops_rocev2 for iWARP and RoCEv2 protocols, respectively.
>>>
>> Hi, Boshi
>>
>>  From alomost all of the RDMA users, it seems that RoCEv2 protocol is required while very few users request iWARP protocol in their production hosts. But in the erdma HW/FW, this iWARP protocol is supported. Is this iWARP protocol for some special use cases in the Ali-Cloud environment?
>>
> 
> Hi, Yanjun,
> 
> iWarp & TCP have some good features, such as Tail Loss Probe(TLP), selective ACK and
> out-of-order DDP, so that can get better performance in large-scale lossy network. The

Thanks for your reply. The design purpose of RDMA is for big bandwidth 
and low latency network, that is, a loss-less network. And most users 
work in this loss-less network. I can not image why rdma should work in 
this kind of large-scale lossy network.

Anyway
Reviewed-by: Zhu Yanjun <yanjun.zhu@linux.dev>

Zhu Yanjun

> current usage scenarios include HPC industrial simulation, redis, PolarDB and big data
> in public cloud environment.
> 
> Thanks,
> Cheng Xu
> 
>> I am just curious about this, not to be against this patch series. If this is related with the Ali-Cloud security, you can ignore this.
>>
>> Thanks,
>> Zhu Yanjun
>>
> 


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH for-next 2/8] RDMA/erdma: Add GID table management interfaces
  2024-11-28  2:35     ` Boshi Yu
@ 2024-11-29  8:54       ` Zhu Yanjun
  2024-11-29 11:18         ` Boshi Yu
  0 siblings, 1 reply; 21+ messages in thread
From: Zhu Yanjun @ 2024-11-29  8:54 UTC (permalink / raw)
  To: Boshi Yu, jgg, leon, chengyou; +Cc: linux-rdma, kaishen

On 28.11.24 03:35, Boshi Yu wrote:
> On Tue, Nov 26, 2024 at 04:51:02PM +0100, Zhu Yanjun wrote:
>> 在 2024/11/26 7:59, Boshi Yu 写道:
>>> The erdma_add_gid() interface inserts a GID entry at the
>>> specified index. The erdma_del_gid() interface deletes the
>>> GID entry at the specified index. Additionally, programs
>>> can invoke the erdma_query_port() and erdma_get_port_immutable()
>>> interfaces to query the GID table length.
>>>
>>> Signed-off-by: Boshi Yu <boshiyu@linux.alibaba.com>
>>> Reviewed-by: Cheng Xu <chengyou@linux.alibaba.com>
>>> ---
>>>    drivers/infiniband/hw/erdma/erdma.h       |  1 +
>>>    drivers/infiniband/hw/erdma/erdma_hw.h    | 28 +++++++++++-
>>>    drivers/infiniband/hw/erdma/erdma_main.c  |  3 ++
>>>    drivers/infiniband/hw/erdma/erdma_verbs.c | 56 +++++++++++++++++++++--
>>>    drivers/infiniband/hw/erdma/erdma_verbs.h | 12 +++++
>>>    5 files changed, 96 insertions(+), 4 deletions(-)
>>>
>>> diff --git a/drivers/infiniband/hw/erdma/erdma.h b/drivers/infiniband/hw/erdma/erdma.h
>>> index ad4dc1a4bdc7..42dabf674f5d 100644
>>> --- a/drivers/infiniband/hw/erdma/erdma.h
>>> +++ b/drivers/infiniband/hw/erdma/erdma.h
>>> @@ -148,6 +148,7 @@ struct erdma_devattr {
>>>    	u32 max_mr;
>>>    	u32 max_pd;
>>>    	u32 max_mw;
>>> +	u32 max_gid;
>>>    	u32 local_dma_key;
>>>    };
>>> diff --git a/drivers/infiniband/hw/erdma/erdma_hw.h b/drivers/infiniband/hw/erdma/erdma_hw.h
>>> index 970b392d4fb4..7e03c5f97501 100644
>>> --- a/drivers/infiniband/hw/erdma/erdma_hw.h
>>> +++ b/drivers/infiniband/hw/erdma/erdma_hw.h
>>> @@ -21,6 +21,9 @@
>>>    #define ERDMA_NUM_MSIX_VEC 32U
>>>    #define ERDMA_MSIX_VECTOR_CMDQ 0
>>> +/* RoCEv2 related */
>>> +#define ERDMA_ROCEV2_GID_SIZE 16
>>> +
>>>    /* erdma device protocol type */
>>>    enum erdma_proto_type {
>>>    	ERDMA_PROTO_IWARP = 0,
>>> @@ -143,7 +146,8 @@ enum CMDQ_RDMA_OPCODE {
>>>    	CMDQ_OPCODE_DESTROY_CQ = 5,
>>>    	CMDQ_OPCODE_REFLUSH = 6,
>>>    	CMDQ_OPCODE_REG_MR = 8,
>>> -	CMDQ_OPCODE_DEREG_MR = 9
>>> +	CMDQ_OPCODE_DEREG_MR = 9,
>>> +	CMDQ_OPCODE_SET_GID = 14,
>>>    };
>>>    enum CMDQ_COMMON_OPCODE {
>>> @@ -401,7 +405,29 @@ struct erdma_cmdq_query_stats_resp {
>>>    	u64 rx_pps_meter_drop_packets_cnt;
>>>    };
>>> +enum erdma_network_type {
>>> +	ERDMA_NETWORK_TYPE_IPV4 = 0,
>>> +	ERDMA_NETWORK_TYPE_IPV6 = 1,
>>> +};
>>
>> In the file include/rdma/ib_verbs.h
>>
>> "
>> ...
>>   183 enum rdma_network_type {
>> ...
>>   186     RDMA_NETWORK_IPV4,
>>   187     RDMA_NETWORK_IPV6
>>   188 };
>> ...
>> "
>> Not sure why the above RDMA_NETWORK_IPV4 and RDMA_NETWORK_IPV6 are not used.
>>
>> Zhu Yanjun
>>
> 
> Hi, Yanjun,
> 
> Given that the values for RDMA_NETWORK_IPV4 and RDMA_NETWORK_IPV6 are 2 and 3,
> respectively, we would need 2 bits to store the network type if we use them
> directly. However, since we only need to differentiate between IPv4 and IPv6
> for the RoCEv2 protocol, 1 bit is sufficient.

I can not get you. You mean, you want to use 1 bit to differentiate 
between IPv4 and IPv6. How to implement this idea? Can you show us the 
difference of 1 bit (enum erdma_network_type) and 2 bits (enum 
rdma_network_type) in driver?

Thanks,

Zhu Yanjun
> 
> Thanks,
> Boshi Yu
> 
>>> +
>>> +enum erdma_set_gid_op {
>>> +	ERDMA_SET_GID_OP_ADD = 0,
>>> +	ERDMA_SET_GID_OP_DEL = 1,
>>> +};
>>> +
>>> +/* set gid cfg */
>>> +#define ERDMA_CMD_SET_GID_SGID_IDX_MASK GENMASK(15, 0)
>>> +#define ERDMA_CMD_SET_GID_NTYPE_MASK BIT(16)
>>> +#define ERDMA_CMD_SET_GID_OP_MASK BIT(31)
>>> +
>>> +struct erdma_cmdq_set_gid_req {
>>> +	u64 hdr;
>>> +	u32 cfg;
>>> +	u8 gid[ERDMA_ROCEV2_GID_SIZE];
>>> +};
>>> +
>>>    /* cap qword 0 definition */
>>> +#define ERDMA_CMD_DEV_CAP_MAX_GID_MASK GENMASK_ULL(51, 48)
>>>    #define ERDMA_CMD_DEV_CAP_MAX_CQE_MASK GENMASK_ULL(47, 40)
>>>    #define ERDMA_CMD_DEV_CAP_FLAGS_MASK GENMASK_ULL(31, 24)
>>>    #define ERDMA_CMD_DEV_CAP_MAX_RECV_WR_MASK GENMASK_ULL(23, 16)
>>> diff --git a/drivers/infiniband/hw/erdma/erdma_main.c b/drivers/infiniband/hw/erdma/erdma_main.c
>>> index b6706c74cd96..d72b85e8971d 100644
>>> --- a/drivers/infiniband/hw/erdma/erdma_main.c
>>> +++ b/drivers/infiniband/hw/erdma/erdma_main.c
>>> @@ -404,6 +404,7 @@ static int erdma_dev_attrs_init(struct erdma_dev *dev)
>>>    	dev->attrs.max_mr_size = 1ULL << ERDMA_GET_CAP(MAX_MR_SIZE, cap0);
>>>    	dev->attrs.max_mw = 1 << ERDMA_GET_CAP(MAX_MW, cap1);
>>>    	dev->attrs.max_recv_wr = 1 << ERDMA_GET_CAP(MAX_RECV_WR, cap0);
>>> +	dev->attrs.max_gid = 1 << ERDMA_GET_CAP(MAX_GID, cap0);
>>>    	dev->attrs.local_dma_key = ERDMA_GET_CAP(DMA_LOCAL_KEY, cap1);
>>>    	dev->attrs.cc = ERDMA_GET_CAP(DEFAULT_CC, cap1);
>>>    	dev->attrs.max_qp = ERDMA_NQP_PER_QBLOCK * ERDMA_GET_CAP(QBLOCK, cap1);
>>> @@ -482,6 +483,8 @@ static void erdma_res_cb_free(struct erdma_dev *dev)
>>>    static const struct ib_device_ops erdma_device_ops_rocev2 = {
>>>    	.get_link_layer = erdma_get_link_layer,
>>> +	.add_gid = erdma_add_gid,
>>> +	.del_gid = erdma_del_gid,
>>>    };
>>>    static const struct ib_device_ops erdma_device_ops_iwarp = {
>>> diff --git a/drivers/infiniband/hw/erdma/erdma_verbs.c b/drivers/infiniband/hw/erdma/erdma_verbs.c
>>> index 3b7e55515cfd..9944eed584ec 100644
>>> --- a/drivers/infiniband/hw/erdma/erdma_verbs.c
>>> +++ b/drivers/infiniband/hw/erdma/erdma_verbs.c
>>> @@ -367,7 +367,13 @@ int erdma_query_port(struct ib_device *ibdev, u32 port,
>>>    	memset(attr, 0, sizeof(*attr));
>>> -	attr->gid_tbl_len = 1;
>>> +	if (erdma_device_iwarp(dev)) {
>>> +		attr->gid_tbl_len = 1;
>>> +	} else {
>>> +		attr->gid_tbl_len = dev->attrs.max_gid;
>>> +		attr->ip_gids = true;
>>> +	}
>>> +
>>>    	attr->port_cap_flags = IB_PORT_CM_SUP | IB_PORT_DEVICE_MGMT_SUP;
>>>    	attr->max_msg_sz = -1;
>>> @@ -399,14 +405,14 @@ int erdma_get_port_immutable(struct ib_device *ibdev, u32 port,
>>>    	if (erdma_device_iwarp(dev)) {
>>>    		port_immutable->core_cap_flags = RDMA_CORE_PORT_IWARP;
>>> +		port_immutable->gid_tbl_len = 1;
>>>    	} else {
>>>    		port_immutable->core_cap_flags =
>>>    			RDMA_CORE_PORT_IBA_ROCE_UDP_ENCAP;
>>>    		port_immutable->max_mad_size = IB_MGMT_MAD_SIZE;
>>> +		port_immutable->gid_tbl_len = dev->attrs.max_gid;
>>>    	}
>>> -	port_immutable->gid_tbl_len = 1;
>>> -
>>>    	return 0;
>>>    }
>>> @@ -1853,3 +1859,47 @@ enum rdma_link_layer erdma_get_link_layer(struct ib_device *ibdev, u32 port_num)
>>>    {
>>>    	return IB_LINK_LAYER_ETHERNET;
>>>    }
>>> +
>>> +static int erdma_set_gid(struct erdma_dev *dev, u8 op, u32 idx,
>>> +			 const union ib_gid *gid)
>>> +{
>>> +	struct erdma_cmdq_set_gid_req req;
>>> +	u8 ntype;
>>> +
>>> +	req.cfg = FIELD_PREP(ERDMA_CMD_SET_GID_SGID_IDX_MASK, idx) |
>>> +		  FIELD_PREP(ERDMA_CMD_SET_GID_OP_MASK, op);
>>> +
>>> +	if (op == ERDMA_SET_GID_OP_ADD) {
>>> +		if (ipv6_addr_v4mapped((struct in6_addr *)gid))
>>> +			ntype = ERDMA_NETWORK_TYPE_IPV4;
>>> +		else
>>> +			ntype = ERDMA_NETWORK_TYPE_IPV6;
>>> +
>>> +		req.cfg |= FIELD_PREP(ERDMA_CMD_SET_GID_NTYPE_MASK, ntype);
>>> +
>>> +		memcpy(&req.gid, gid, ERDMA_ROCEV2_GID_SIZE);
>>> +	}
>>> +
>>> +	erdma_cmdq_build_reqhdr(&req.hdr, CMDQ_SUBMOD_RDMA,
>>> +				CMDQ_OPCODE_SET_GID);
>>> +	return erdma_post_cmd_wait(&dev->cmdq, &req, sizeof(req), NULL, NULL);
>>> +}
>>> +
>>> +int erdma_add_gid(const struct ib_gid_attr *attr, void **context)
>>> +{
>>> +	struct erdma_dev *dev = to_edev(attr->device);
>>> +	int ret;
>>> +
>>> +	ret = erdma_check_gid_attr(attr);
>>> +	if (ret)
>>> +		return ret;
>>> +
>>> +	return erdma_set_gid(dev, ERDMA_SET_GID_OP_ADD, attr->index,
>>> +			     &attr->gid);
>>> +}
>>> +
>>> +int erdma_del_gid(const struct ib_gid_attr *attr, void **context)
>>> +{
>>> +	return erdma_set_gid(to_edev(attr->device), ERDMA_SET_GID_OP_DEL,
>>> +			     attr->index, NULL);
>>> +}
>>> diff --git a/drivers/infiniband/hw/erdma/erdma_verbs.h b/drivers/infiniband/hw/erdma/erdma_verbs.h
>>> index 90e2b35a0973..23cfeaf79eaa 100644
>>> --- a/drivers/infiniband/hw/erdma/erdma_verbs.h
>>> +++ b/drivers/infiniband/hw/erdma/erdma_verbs.h
>>> @@ -326,6 +326,16 @@ static inline struct erdma_cq *to_ecq(struct ib_cq *ibcq)
>>>    	return container_of(ibcq, struct erdma_cq, ibcq);
>>>    }
>>> +static inline int erdma_check_gid_attr(const struct ib_gid_attr *attr)
>>> +{
>>> +	u8 ntype = rdma_gid_attr_network_type(attr);
>>> +
>>> +	if (ntype != RDMA_NETWORK_IPV4 && ntype != RDMA_NETWORK_IPV6)
>>> +		return -EINVAL;
>>> +
>>> +	return 0;
>>> +}
>>> +
>>>    static inline struct erdma_user_mmap_entry *
>>>    to_emmap(struct rdma_user_mmap_entry *ibmmap)
>>>    {
>>> @@ -382,5 +392,7 @@ int erdma_get_hw_stats(struct ib_device *ibdev, struct rdma_hw_stats *stats,
>>>    		       u32 port, int index);
>>>    enum rdma_link_layer erdma_get_link_layer(struct ib_device *ibdev,
>>>    					  u32 port_num);
>>> +int erdma_add_gid(const struct ib_gid_attr *attr, void **context);
>>> +int erdma_del_gid(const struct ib_gid_attr *attr, void **context);
>>>    #endif


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH for-next 2/8] RDMA/erdma: Add GID table management interfaces
  2024-11-29  8:54       ` Zhu Yanjun
@ 2024-11-29 11:18         ` Boshi Yu
  2024-11-29 18:40           ` Zhu Yanjun
  0 siblings, 1 reply; 21+ messages in thread
From: Boshi Yu @ 2024-11-29 11:18 UTC (permalink / raw)
  To: Zhu Yanjun, jgg, leon, chengyou; +Cc: linux-rdma, kaishen



在 2024/11/29 16:54, Zhu Yanjun wrote:
> On 28.11.24 03:35, Boshi Yu wrote:
>> On Tue, Nov 26, 2024 at 04:51:02PM +0100, Zhu Yanjun wrote:
>>> 在 2024/11/26 7:59, Boshi Yu 写道:
>>>> The erdma_add_gid() interface inserts a GID entry at the
>>>> specified index. The erdma_del_gid() interface deletes the
>>>> GID entry at the specified index. Additionally, programs
>>>> can invoke the erdma_query_port() and erdma_get_port_immutable()
>>>> interfaces to query the GID table length.
>>>>
>>>> Signed-off-by: Boshi Yu <boshiyu@linux.alibaba.com>
>>>> Reviewed-by: Cheng Xu <chengyou@linux.alibaba.com>
>>>> ---
>>>>    drivers/infiniband/hw/erdma/erdma.h       |  1 +
>>>>    drivers/infiniband/hw/erdma/erdma_hw.h    | 28 +++++++++++-
>>>>    drivers/infiniband/hw/erdma/erdma_main.c  |  3 ++
>>>>    drivers/infiniband/hw/erdma/erdma_verbs.c | 56 ++++++++++++++++++ 
>>>> +++--
>>>>    drivers/infiniband/hw/erdma/erdma_verbs.h | 12 +++++
>>>>    5 files changed, 96 insertions(+), 4 deletions(-)
>>>>
>>>> diff --git a/drivers/infiniband/hw/erdma/erdma.h b/drivers/ 
>>>> infiniband/hw/erdma/erdma.h
>>>> index ad4dc1a4bdc7..42dabf674f5d 100644
>>>> --- a/drivers/infiniband/hw/erdma/erdma.h
>>>> +++ b/drivers/infiniband/hw/erdma/erdma.h
>>>> @@ -148,6 +148,7 @@ struct erdma_devattr {
>>>>        u32 max_mr;
>>>>        u32 max_pd;
>>>>        u32 max_mw;
>>>> +    u32 max_gid;
>>>>        u32 local_dma_key;
>>>>    };
>>>> diff --git a/drivers/infiniband/hw/erdma/erdma_hw.h b/drivers/ 
>>>> infiniband/hw/erdma/erdma_hw.h
>>>> index 970b392d4fb4..7e03c5f97501 100644
>>>> --- a/drivers/infiniband/hw/erdma/erdma_hw.h
>>>> +++ b/drivers/infiniband/hw/erdma/erdma_hw.h
>>>> @@ -21,6 +21,9 @@
>>>>    #define ERDMA_NUM_MSIX_VEC 32U
>>>>    #define ERDMA_MSIX_VECTOR_CMDQ 0
>>>> +/* RoCEv2 related */
>>>> +#define ERDMA_ROCEV2_GID_SIZE 16
>>>> +
>>>>    /* erdma device protocol type */
>>>>    enum erdma_proto_type {
>>>>        ERDMA_PROTO_IWARP = 0,
>>>> @@ -143,7 +146,8 @@ enum CMDQ_RDMA_OPCODE {
>>>>        CMDQ_OPCODE_DESTROY_CQ = 5,
>>>>        CMDQ_OPCODE_REFLUSH = 6,
>>>>        CMDQ_OPCODE_REG_MR = 8,
>>>> -    CMDQ_OPCODE_DEREG_MR = 9
>>>> +    CMDQ_OPCODE_DEREG_MR = 9,
>>>> +    CMDQ_OPCODE_SET_GID = 14,
>>>>    };
>>>>    enum CMDQ_COMMON_OPCODE {
>>>> @@ -401,7 +405,29 @@ struct erdma_cmdq_query_stats_resp {
>>>>        u64 rx_pps_meter_drop_packets_cnt;
>>>>    };
>>>> +enum erdma_network_type {
>>>> +    ERDMA_NETWORK_TYPE_IPV4 = 0,
>>>> +    ERDMA_NETWORK_TYPE_IPV6 = 1,
>>>> +};
>>>
>>> In the file include/rdma/ib_verbs.h
>>>
>>> "
>>> ...
>>>   183 enum rdma_network_type {
>>> ...
>>>   186     RDMA_NETWORK_IPV4,
>>>   187     RDMA_NETWORK_IPV6
>>>   188 };
>>> ...
>>> "
>>> Not sure why the above RDMA_NETWORK_IPV4 and RDMA_NETWORK_IPV6 are 
>>> not used.
>>>
>>> Zhu Yanjun
>>>
>>
>> Hi, Yanjun,
>>
>> Given that the values for RDMA_NETWORK_IPV4 and RDMA_NETWORK_IPV6 are 
>> 2 and 3,
>> respectively, we would need 2 bits to store the network type if we use 
>> them
>> directly. However, since we only need to differentiate between IPv4 
>> and IPv6
>> for the RoCEv2 protocol, 1 bit is sufficient.
> 
> I can not get you. You mean, you want to use 1 bit to differentiate 
> between IPv4 and IPv6. How to implement this idea? Can you show us the 
> difference of 1 bit (enum erdma_network_type) and 2 bits (enum 
> rdma_network_type) in driver?
> 
> Thanks,
> 
> Zhu Yanjun

Hi, Yanjun,

I'm sorry for not explaining this issue clearly. The enum 
erdma_network_type is actually a convention between the erdma hardware 
and the erdma driver. We just want to use fewer bits to pass the 
information to the hardware, independent of the kernel definition.

Thanks,

Boshi Yu

>>
>> Thanks,
>> Boshi Yu
>>
>>>> +
>>>> +enum erdma_set_gid_op {
>>>> +    ERDMA_SET_GID_OP_ADD = 0,
>>>> +    ERDMA_SET_GID_OP_DEL = 1,
>>>> +};
>>>> +
>>>> +/* set gid cfg */
>>>> +#define ERDMA_CMD_SET_GID_SGID_IDX_MASK GENMASK(15, 0)
>>>> +#define ERDMA_CMD_SET_GID_NTYPE_MASK BIT(16)
>>>> +#define ERDMA_CMD_SET_GID_OP_MASK BIT(31)
>>>> +
>>>> +struct erdma_cmdq_set_gid_req {
>>>> +    u64 hdr;
>>>> +    u32 cfg;
>>>> +    u8 gid[ERDMA_ROCEV2_GID_SIZE];
>>>> +};
>>>> +
>>>>    /* cap qword 0 definition */
>>>> +#define ERDMA_CMD_DEV_CAP_MAX_GID_MASK GENMASK_ULL(51, 48)
>>>>    #define ERDMA_CMD_DEV_CAP_MAX_CQE_MASK GENMASK_ULL(47, 40)
>>>>    #define ERDMA_CMD_DEV_CAP_FLAGS_MASK GENMASK_ULL(31, 24)
>>>>    #define ERDMA_CMD_DEV_CAP_MAX_RECV_WR_MASK GENMASK_ULL(23, 16)
>>>> diff --git a/drivers/infiniband/hw/erdma/erdma_main.c b/drivers/ 
>>>> infiniband/hw/erdma/erdma_main.c
>>>> index b6706c74cd96..d72b85e8971d 100644
>>>> --- a/drivers/infiniband/hw/erdma/erdma_main.c
>>>> +++ b/drivers/infiniband/hw/erdma/erdma_main.c
>>>> @@ -404,6 +404,7 @@ static int erdma_dev_attrs_init(struct erdma_dev 
>>>> *dev)
>>>>        dev->attrs.max_mr_size = 1ULL << ERDMA_GET_CAP(MAX_MR_SIZE, 
>>>> cap0);
>>>>        dev->attrs.max_mw = 1 << ERDMA_GET_CAP(MAX_MW, cap1);
>>>>        dev->attrs.max_recv_wr = 1 << ERDMA_GET_CAP(MAX_RECV_WR, cap0);
>>>> +    dev->attrs.max_gid = 1 << ERDMA_GET_CAP(MAX_GID, cap0);
>>>>        dev->attrs.local_dma_key = ERDMA_GET_CAP(DMA_LOCAL_KEY, cap1);
>>>>        dev->attrs.cc = ERDMA_GET_CAP(DEFAULT_CC, cap1);
>>>>        dev->attrs.max_qp = ERDMA_NQP_PER_QBLOCK * 
>>>> ERDMA_GET_CAP(QBLOCK, cap1);
>>>> @@ -482,6 +483,8 @@ static void erdma_res_cb_free(struct erdma_dev 
>>>> *dev)
>>>>    static const struct ib_device_ops erdma_device_ops_rocev2 = {
>>>>        .get_link_layer = erdma_get_link_layer,
>>>> +    .add_gid = erdma_add_gid,
>>>> +    .del_gid = erdma_del_gid,
>>>>    };
>>>>    static const struct ib_device_ops erdma_device_ops_iwarp = {
>>>> diff --git a/drivers/infiniband/hw/erdma/erdma_verbs.c b/drivers/ 
>>>> infiniband/hw/erdma/erdma_verbs.c
>>>> index 3b7e55515cfd..9944eed584ec 100644
>>>> --- a/drivers/infiniband/hw/erdma/erdma_verbs.c
>>>> +++ b/drivers/infiniband/hw/erdma/erdma_verbs.c
>>>> @@ -367,7 +367,13 @@ int erdma_query_port(struct ib_device *ibdev, 
>>>> u32 port,
>>>>        memset(attr, 0, sizeof(*attr));
>>>> -    attr->gid_tbl_len = 1;
>>>> +    if (erdma_device_iwarp(dev)) {
>>>> +        attr->gid_tbl_len = 1;
>>>> +    } else {
>>>> +        attr->gid_tbl_len = dev->attrs.max_gid;
>>>> +        attr->ip_gids = true;
>>>> +    }
>>>> +
>>>>        attr->port_cap_flags = IB_PORT_CM_SUP | IB_PORT_DEVICE_MGMT_SUP;
>>>>        attr->max_msg_sz = -1;
>>>> @@ -399,14 +405,14 @@ int erdma_get_port_immutable(struct ib_device 
>>>> *ibdev, u32 port,
>>>>        if (erdma_device_iwarp(dev)) {
>>>>            port_immutable->core_cap_flags = RDMA_CORE_PORT_IWARP;
>>>> +        port_immutable->gid_tbl_len = 1;
>>>>        } else {
>>>>            port_immutable->core_cap_flags =
>>>>                RDMA_CORE_PORT_IBA_ROCE_UDP_ENCAP;
>>>>            port_immutable->max_mad_size = IB_MGMT_MAD_SIZE;
>>>> +        port_immutable->gid_tbl_len = dev->attrs.max_gid;
>>>>        }
>>>> -    port_immutable->gid_tbl_len = 1;
>>>> -
>>>>        return 0;
>>>>    }
>>>> @@ -1853,3 +1859,47 @@ enum rdma_link_layer 
>>>> erdma_get_link_layer(struct ib_device *ibdev, u32 port_num)
>>>>    {
>>>>        return IB_LINK_LAYER_ETHERNET;
>>>>    }
>>>> +
>>>> +static int erdma_set_gid(struct erdma_dev *dev, u8 op, u32 idx,
>>>> +             const union ib_gid *gid)
>>>> +{
>>>> +    struct erdma_cmdq_set_gid_req req;
>>>> +    u8 ntype;
>>>> +
>>>> +    req.cfg = FIELD_PREP(ERDMA_CMD_SET_GID_SGID_IDX_MASK, idx) |
>>>> +          FIELD_PREP(ERDMA_CMD_SET_GID_OP_MASK, op);
>>>> +
>>>> +    if (op == ERDMA_SET_GID_OP_ADD) {
>>>> +        if (ipv6_addr_v4mapped((struct in6_addr *)gid))
>>>> +            ntype = ERDMA_NETWORK_TYPE_IPV4;
>>>> +        else
>>>> +            ntype = ERDMA_NETWORK_TYPE_IPV6;
>>>> +
>>>> +        req.cfg |= FIELD_PREP(ERDMA_CMD_SET_GID_NTYPE_MASK, ntype);
>>>> +
>>>> +        memcpy(&req.gid, gid, ERDMA_ROCEV2_GID_SIZE);
>>>> +    }
>>>> +
>>>> +    erdma_cmdq_build_reqhdr(&req.hdr, CMDQ_SUBMOD_RDMA,
>>>> +                CMDQ_OPCODE_SET_GID);
>>>> +    return erdma_post_cmd_wait(&dev->cmdq, &req, sizeof(req), NULL, 
>>>> NULL);
>>>> +}
>>>> +
>>>> +int erdma_add_gid(const struct ib_gid_attr *attr, void **context)
>>>> +{
>>>> +    struct erdma_dev *dev = to_edev(attr->device);
>>>> +    int ret;
>>>> +
>>>> +    ret = erdma_check_gid_attr(attr);
>>>> +    if (ret)
>>>> +        return ret;
>>>> +
>>>> +    return erdma_set_gid(dev, ERDMA_SET_GID_OP_ADD, attr->index,
>>>> +                 &attr->gid);
>>>> +}
>>>> +
>>>> +int erdma_del_gid(const struct ib_gid_attr *attr, void **context)
>>>> +{
>>>> +    return erdma_set_gid(to_edev(attr->device), ERDMA_SET_GID_OP_DEL,
>>>> +                 attr->index, NULL);
>>>> +}
>>>> diff --git a/drivers/infiniband/hw/erdma/erdma_verbs.h b/drivers/ 
>>>> infiniband/hw/erdma/erdma_verbs.h
>>>> index 90e2b35a0973..23cfeaf79eaa 100644
>>>> --- a/drivers/infiniband/hw/erdma/erdma_verbs.h
>>>> +++ b/drivers/infiniband/hw/erdma/erdma_verbs.h
>>>> @@ -326,6 +326,16 @@ static inline struct erdma_cq *to_ecq(struct 
>>>> ib_cq *ibcq)
>>>>        return container_of(ibcq, struct erdma_cq, ibcq);
>>>>    }
>>>> +static inline int erdma_check_gid_attr(const struct ib_gid_attr *attr)
>>>> +{
>>>> +    u8 ntype = rdma_gid_attr_network_type(attr);
>>>> +
>>>> +    if (ntype != RDMA_NETWORK_IPV4 && ntype != RDMA_NETWORK_IPV6)
>>>> +        return -EINVAL;
>>>> +
>>>> +    return 0;
>>>> +}
>>>> +
>>>>    static inline struct erdma_user_mmap_entry *
>>>>    to_emmap(struct rdma_user_mmap_entry *ibmmap)
>>>>    {
>>>> @@ -382,5 +392,7 @@ int erdma_get_hw_stats(struct ib_device *ibdev, 
>>>> struct rdma_hw_stats *stats,
>>>>                   u32 port, int index);
>>>>    enum rdma_link_layer erdma_get_link_layer(struct ib_device *ibdev,
>>>>                          u32 port_num);
>>>> +int erdma_add_gid(const struct ib_gid_attr *attr, void **context);
>>>> +int erdma_del_gid(const struct ib_gid_attr *attr, void **context);
>>>>    #endif


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH for-next 2/8] RDMA/erdma: Add GID table management interfaces
  2024-11-29 11:18         ` Boshi Yu
@ 2024-11-29 18:40           ` Zhu Yanjun
  0 siblings, 0 replies; 21+ messages in thread
From: Zhu Yanjun @ 2024-11-29 18:40 UTC (permalink / raw)
  To: Boshi Yu, jgg, leon, chengyou; +Cc: linux-rdma, kaishen

在 2024/11/29 12:18, Boshi Yu 写道:
> 
> 
> 在 2024/11/29 16:54, Zhu Yanjun wrote:
>> On 28.11.24 03:35, Boshi Yu wrote:
>>> On Tue, Nov 26, 2024 at 04:51:02PM +0100, Zhu Yanjun wrote:
>>>> 在 2024/11/26 7:59, Boshi Yu 写道:
>>>>> The erdma_add_gid() interface inserts a GID entry at the
>>>>> specified index. The erdma_del_gid() interface deletes the
>>>>> GID entry at the specified index. Additionally, programs
>>>>> can invoke the erdma_query_port() and erdma_get_port_immutable()
>>>>> interfaces to query the GID table length.
>>>>>
>>>>> Signed-off-by: Boshi Yu <boshiyu@linux.alibaba.com>
>>>>> Reviewed-by: Cheng Xu <chengyou@linux.alibaba.com>
>>>>> ---
>>>>>    drivers/infiniband/hw/erdma/erdma.h       |  1 +
>>>>>    drivers/infiniband/hw/erdma/erdma_hw.h    | 28 +++++++++++-
>>>>>    drivers/infiniband/hw/erdma/erdma_main.c  |  3 ++
>>>>>    drivers/infiniband/hw/erdma/erdma_verbs.c | 56 +++++++++++++++++ 
>>>>> + +++--
>>>>>    drivers/infiniband/hw/erdma/erdma_verbs.h | 12 +++++
>>>>>    5 files changed, 96 insertions(+), 4 deletions(-)
>>>>>
>>>>> diff --git a/drivers/infiniband/hw/erdma/erdma.h b/drivers/ 
>>>>> infiniband/hw/erdma/erdma.h
>>>>> index ad4dc1a4bdc7..42dabf674f5d 100644
>>>>> --- a/drivers/infiniband/hw/erdma/erdma.h
>>>>> +++ b/drivers/infiniband/hw/erdma/erdma.h
>>>>> @@ -148,6 +148,7 @@ struct erdma_devattr {
>>>>>        u32 max_mr;
>>>>>        u32 max_pd;
>>>>>        u32 max_mw;
>>>>> +    u32 max_gid;
>>>>>        u32 local_dma_key;
>>>>>    };
>>>>> diff --git a/drivers/infiniband/hw/erdma/erdma_hw.h b/drivers/ 
>>>>> infiniband/hw/erdma/erdma_hw.h
>>>>> index 970b392d4fb4..7e03c5f97501 100644
>>>>> --- a/drivers/infiniband/hw/erdma/erdma_hw.h
>>>>> +++ b/drivers/infiniband/hw/erdma/erdma_hw.h
>>>>> @@ -21,6 +21,9 @@
>>>>>    #define ERDMA_NUM_MSIX_VEC 32U
>>>>>    #define ERDMA_MSIX_VECTOR_CMDQ 0
>>>>> +/* RoCEv2 related */
>>>>> +#define ERDMA_ROCEV2_GID_SIZE 16
>>>>> +
>>>>>    /* erdma device protocol type */
>>>>>    enum erdma_proto_type {
>>>>>        ERDMA_PROTO_IWARP = 0,
>>>>> @@ -143,7 +146,8 @@ enum CMDQ_RDMA_OPCODE {
>>>>>        CMDQ_OPCODE_DESTROY_CQ = 5,
>>>>>        CMDQ_OPCODE_REFLUSH = 6,
>>>>>        CMDQ_OPCODE_REG_MR = 8,
>>>>> -    CMDQ_OPCODE_DEREG_MR = 9
>>>>> +    CMDQ_OPCODE_DEREG_MR = 9,
>>>>> +    CMDQ_OPCODE_SET_GID = 14,
>>>>>    };
>>>>>    enum CMDQ_COMMON_OPCODE {
>>>>> @@ -401,7 +405,29 @@ struct erdma_cmdq_query_stats_resp {
>>>>>        u64 rx_pps_meter_drop_packets_cnt;
>>>>>    };
>>>>> +enum erdma_network_type {
>>>>> +    ERDMA_NETWORK_TYPE_IPV4 = 0,
>>>>> +    ERDMA_NETWORK_TYPE_IPV6 = 1,
>>>>> +};
>>>>
>>>> In the file include/rdma/ib_verbs.h
>>>>
>>>> "
>>>> ...
>>>>   183 enum rdma_network_type {
>>>> ...
>>>>   186     RDMA_NETWORK_IPV4,
>>>>   187     RDMA_NETWORK_IPV6
>>>>   188 };
>>>> ...
>>>> "
>>>> Not sure why the above RDMA_NETWORK_IPV4 and RDMA_NETWORK_IPV6 are 
>>>> not used.
>>>>
>>>> Zhu Yanjun
>>>>
>>>
>>> Hi, Yanjun,
>>>
>>> Given that the values for RDMA_NETWORK_IPV4 and RDMA_NETWORK_IPV6 are 
>>> 2 and 3,
>>> respectively, we would need 2 bits to store the network type if we 
>>> use them
>>> directly. However, since we only need to differentiate between IPv4 
>>> and IPv6
>>> for the RoCEv2 protocol, 1 bit is sufficient.
>>
>> I can not get you. You mean, you want to use 1 bit to differentiate 
>> between IPv4 and IPv6. How to implement this idea? Can you show us the 
>> difference of 1 bit (enum erdma_network_type) and 2 bits (enum 
>> rdma_network_type) in driver?
>>
>> Thanks,
>>
>> Zhu Yanjun
> 
> Hi, Yanjun,
> 
> I'm sorry for not explaining this issue clearly. The enum 
> erdma_network_type is actually a convention between the erdma hardware 
> and the erdma driver. We just want to use fewer bits to pass the 
> information to the hardware, independent of the kernel definition.

Thanks a lot. This makes sense to me. The enum erdma_network_type is 1 
bit, including 0, 1. This can let the driver use fewer bits to 
communicate with the hardware.

Reviewed-by: Zhu Yanjun <yanjun.zhu@linux.dev>

Zhu Yanjun

> 
> Thanks,
> 
> Boshi Yu
> 
>>>
>>> Thanks,
>>> Boshi Yu
>>>
>>>>> +
>>>>> +enum erdma_set_gid_op {
>>>>> +    ERDMA_SET_GID_OP_ADD = 0,
>>>>> +    ERDMA_SET_GID_OP_DEL = 1,
>>>>> +};
>>>>> +
>>>>> +/* set gid cfg */
>>>>> +#define ERDMA_CMD_SET_GID_SGID_IDX_MASK GENMASK(15, 0)
>>>>> +#define ERDMA_CMD_SET_GID_NTYPE_MASK BIT(16)
>>>>> +#define ERDMA_CMD_SET_GID_OP_MASK BIT(31)
>>>>> +
>>>>> +struct erdma_cmdq_set_gid_req {
>>>>> +    u64 hdr;
>>>>> +    u32 cfg;
>>>>> +    u8 gid[ERDMA_ROCEV2_GID_SIZE];
>>>>> +};
>>>>> +
>>>>>    /* cap qword 0 definition */
>>>>> +#define ERDMA_CMD_DEV_CAP_MAX_GID_MASK GENMASK_ULL(51, 48)
>>>>>    #define ERDMA_CMD_DEV_CAP_MAX_CQE_MASK GENMASK_ULL(47, 40)
>>>>>    #define ERDMA_CMD_DEV_CAP_FLAGS_MASK GENMASK_ULL(31, 24)
>>>>>    #define ERDMA_CMD_DEV_CAP_MAX_RECV_WR_MASK GENMASK_ULL(23, 16)
>>>>> diff --git a/drivers/infiniband/hw/erdma/erdma_main.c b/drivers/ 
>>>>> infiniband/hw/erdma/erdma_main.c
>>>>> index b6706c74cd96..d72b85e8971d 100644
>>>>> --- a/drivers/infiniband/hw/erdma/erdma_main.c
>>>>> +++ b/drivers/infiniband/hw/erdma/erdma_main.c
>>>>> @@ -404,6 +404,7 @@ static int erdma_dev_attrs_init(struct 
>>>>> erdma_dev *dev)
>>>>>        dev->attrs.max_mr_size = 1ULL << ERDMA_GET_CAP(MAX_MR_SIZE, 
>>>>> cap0);
>>>>>        dev->attrs.max_mw = 1 << ERDMA_GET_CAP(MAX_MW, cap1);
>>>>>        dev->attrs.max_recv_wr = 1 << ERDMA_GET_CAP(MAX_RECV_WR, cap0);
>>>>> +    dev->attrs.max_gid = 1 << ERDMA_GET_CAP(MAX_GID, cap0);
>>>>>        dev->attrs.local_dma_key = ERDMA_GET_CAP(DMA_LOCAL_KEY, cap1);
>>>>>        dev->attrs.cc = ERDMA_GET_CAP(DEFAULT_CC, cap1);
>>>>>        dev->attrs.max_qp = ERDMA_NQP_PER_QBLOCK * 
>>>>> ERDMA_GET_CAP(QBLOCK, cap1);
>>>>> @@ -482,6 +483,8 @@ static void erdma_res_cb_free(struct erdma_dev 
>>>>> *dev)
>>>>>    static const struct ib_device_ops erdma_device_ops_rocev2 = {
>>>>>        .get_link_layer = erdma_get_link_layer,
>>>>> +    .add_gid = erdma_add_gid,
>>>>> +    .del_gid = erdma_del_gid,
>>>>>    };
>>>>>    static const struct ib_device_ops erdma_device_ops_iwarp = {
>>>>> diff --git a/drivers/infiniband/hw/erdma/erdma_verbs.c b/drivers/ 
>>>>> infiniband/hw/erdma/erdma_verbs.c
>>>>> index 3b7e55515cfd..9944eed584ec 100644
>>>>> --- a/drivers/infiniband/hw/erdma/erdma_verbs.c
>>>>> +++ b/drivers/infiniband/hw/erdma/erdma_verbs.c
>>>>> @@ -367,7 +367,13 @@ int erdma_query_port(struct ib_device *ibdev, 
>>>>> u32 port,
>>>>>        memset(attr, 0, sizeof(*attr));
>>>>> -    attr->gid_tbl_len = 1;
>>>>> +    if (erdma_device_iwarp(dev)) {
>>>>> +        attr->gid_tbl_len = 1;
>>>>> +    } else {
>>>>> +        attr->gid_tbl_len = dev->attrs.max_gid;
>>>>> +        attr->ip_gids = true;
>>>>> +    }
>>>>> +
>>>>>        attr->port_cap_flags = IB_PORT_CM_SUP | 
>>>>> IB_PORT_DEVICE_MGMT_SUP;
>>>>>        attr->max_msg_sz = -1;
>>>>> @@ -399,14 +405,14 @@ int erdma_get_port_immutable(struct ib_device 
>>>>> *ibdev, u32 port,
>>>>>        if (erdma_device_iwarp(dev)) {
>>>>>            port_immutable->core_cap_flags = RDMA_CORE_PORT_IWARP;
>>>>> +        port_immutable->gid_tbl_len = 1;
>>>>>        } else {
>>>>>            port_immutable->core_cap_flags =
>>>>>                RDMA_CORE_PORT_IBA_ROCE_UDP_ENCAP;
>>>>>            port_immutable->max_mad_size = IB_MGMT_MAD_SIZE;
>>>>> +        port_immutable->gid_tbl_len = dev->attrs.max_gid;
>>>>>        }
>>>>> -    port_immutable->gid_tbl_len = 1;
>>>>> -
>>>>>        return 0;
>>>>>    }
>>>>> @@ -1853,3 +1859,47 @@ enum rdma_link_layer 
>>>>> erdma_get_link_layer(struct ib_device *ibdev, u32 port_num)
>>>>>    {
>>>>>        return IB_LINK_LAYER_ETHERNET;
>>>>>    }
>>>>> +
>>>>> +static int erdma_set_gid(struct erdma_dev *dev, u8 op, u32 idx,
>>>>> +             const union ib_gid *gid)
>>>>> +{
>>>>> +    struct erdma_cmdq_set_gid_req req;
>>>>> +    u8 ntype;
>>>>> +
>>>>> +    req.cfg = FIELD_PREP(ERDMA_CMD_SET_GID_SGID_IDX_MASK, idx) |
>>>>> +          FIELD_PREP(ERDMA_CMD_SET_GID_OP_MASK, op);
>>>>> +
>>>>> +    if (op == ERDMA_SET_GID_OP_ADD) {
>>>>> +        if (ipv6_addr_v4mapped((struct in6_addr *)gid))
>>>>> +            ntype = ERDMA_NETWORK_TYPE_IPV4;
>>>>> +        else
>>>>> +            ntype = ERDMA_NETWORK_TYPE_IPV6;
>>>>> +
>>>>> +        req.cfg |= FIELD_PREP(ERDMA_CMD_SET_GID_NTYPE_MASK, ntype);
>>>>> +
>>>>> +        memcpy(&req.gid, gid, ERDMA_ROCEV2_GID_SIZE);
>>>>> +    }
>>>>> +
>>>>> +    erdma_cmdq_build_reqhdr(&req.hdr, CMDQ_SUBMOD_RDMA,
>>>>> +                CMDQ_OPCODE_SET_GID);
>>>>> +    return erdma_post_cmd_wait(&dev->cmdq, &req, sizeof(req), 
>>>>> NULL, NULL);
>>>>> +}
>>>>> +
>>>>> +int erdma_add_gid(const struct ib_gid_attr *attr, void **context)
>>>>> +{
>>>>> +    struct erdma_dev *dev = to_edev(attr->device);
>>>>> +    int ret;
>>>>> +
>>>>> +    ret = erdma_check_gid_attr(attr);
>>>>> +    if (ret)
>>>>> +        return ret;
>>>>> +
>>>>> +    return erdma_set_gid(dev, ERDMA_SET_GID_OP_ADD, attr->index,
>>>>> +                 &attr->gid);
>>>>> +}
>>>>> +
>>>>> +int erdma_del_gid(const struct ib_gid_attr *attr, void **context)
>>>>> +{
>>>>> +    return erdma_set_gid(to_edev(attr->device), ERDMA_SET_GID_OP_DEL,
>>>>> +                 attr->index, NULL);
>>>>> +}
>>>>> diff --git a/drivers/infiniband/hw/erdma/erdma_verbs.h b/drivers/ 
>>>>> infiniband/hw/erdma/erdma_verbs.h
>>>>> index 90e2b35a0973..23cfeaf79eaa 100644
>>>>> --- a/drivers/infiniband/hw/erdma/erdma_verbs.h
>>>>> +++ b/drivers/infiniband/hw/erdma/erdma_verbs.h
>>>>> @@ -326,6 +326,16 @@ static inline struct erdma_cq *to_ecq(struct 
>>>>> ib_cq *ibcq)
>>>>>        return container_of(ibcq, struct erdma_cq, ibcq);
>>>>>    }
>>>>> +static inline int erdma_check_gid_attr(const struct ib_gid_attr 
>>>>> *attr)
>>>>> +{
>>>>> +    u8 ntype = rdma_gid_attr_network_type(attr);
>>>>> +
>>>>> +    if (ntype != RDMA_NETWORK_IPV4 && ntype != RDMA_NETWORK_IPV6)
>>>>> +        return -EINVAL;
>>>>> +
>>>>> +    return 0;
>>>>> +}
>>>>> +
>>>>>    static inline struct erdma_user_mmap_entry *
>>>>>    to_emmap(struct rdma_user_mmap_entry *ibmmap)
>>>>>    {
>>>>> @@ -382,5 +392,7 @@ int erdma_get_hw_stats(struct ib_device *ibdev, 
>>>>> struct rdma_hw_stats *stats,
>>>>>                   u32 port, int index);
>>>>>    enum rdma_link_layer erdma_get_link_layer(struct ib_device *ibdev,
>>>>>                          u32 port_num);
>>>>> +int erdma_add_gid(const struct ib_gid_attr *attr, void **context);
>>>>> +int erdma_del_gid(const struct ib_gid_attr *attr, void **context);
>>>>>    #endif
> 


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH for-next 1/8] RDMA/erdma: Probe the erdma RoCEv2 device
  2024-11-26  6:59 ` [PATCH for-next 1/8] RDMA/erdma: Probe the erdma RoCEv2 device Boshi Yu
  2024-11-26 15:36   ` Zhu Yanjun
@ 2024-12-04 14:03   ` Leon Romanovsky
  2024-12-05  2:46     ` Boshi Yu
  1 sibling, 1 reply; 21+ messages in thread
From: Leon Romanovsky @ 2024-12-04 14:03 UTC (permalink / raw)
  To: Boshi Yu; +Cc: jgg, linux-rdma, kaishen, chengyou

On Tue, Nov 26, 2024 at 02:59:07PM +0800, Boshi Yu wrote:
> Currently, the erdma driver supports both the iWARP and RoCEv2 protocols.
> The erdma driver reads the ERDMA_REGS_DEV_PROTO_REG register to identify
> the protocol used by the erdma device. Since each protocol requires
> different ib_device_ops, we introduce the erdma_device_ops_iwarp and
> erdma_device_ops_rocev2 for iWARP and RoCEv2 protocols, respectively.
> 
> Signed-off-by: Boshi Yu <boshiyu@linux.alibaba.com>
> Reviewed-by: Cheng Xu <chengyou@linux.alibaba.com>
> ---
>  drivers/infiniband/hw/erdma/Kconfig       |  2 +-
>  drivers/infiniband/hw/erdma/erdma.h       |  3 +-
>  drivers/infiniband/hw/erdma/erdma_hw.h    |  7 ++++
>  drivers/infiniband/hw/erdma/erdma_main.c  | 47 ++++++++++++++++++-----
>  drivers/infiniband/hw/erdma/erdma_verbs.c | 16 +++++++-
>  drivers/infiniband/hw/erdma/erdma_verbs.h | 12 ++++++
>  6 files changed, 75 insertions(+), 12 deletions(-)

<...>

> +++ b/drivers/infiniband/hw/erdma/erdma_main.c
> @@ -172,6 +172,12 @@ static int erdma_device_init(struct erdma_dev *dev, struct pci_dev *pdev)
>  {
>  	int ret;
>  
> +	dev->proto = erdma_reg_read32(dev, ERDMA_REGS_DEV_PROTO_REG);
> +	if (!erdma_device_iwarp(dev) && !erdma_device_rocev2(dev)) {

Why do you need this check? Your old driver which supports only iwarp
doesn't have this check, so why did you suddenly need it for roce? 

> +		dev_err(&pdev->dev, "Unsupported protocol: %d\n", dev->proto);
> +		return -ENODEV;
> +	}
> +

Thanks

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH for-next 4/8] RDMA/erdma: Add address handle implementation
  2024-11-26  6:59 ` [PATCH for-next 4/8] RDMA/erdma: Add address handle implementation Boshi Yu
@ 2024-12-04 14:11   ` Leon Romanovsky
  2024-12-05  2:54     ` Boshi Yu
  0 siblings, 1 reply; 21+ messages in thread
From: Leon Romanovsky @ 2024-12-04 14:11 UTC (permalink / raw)
  To: Boshi Yu; +Cc: jgg, linux-rdma, kaishen, chengyou

On Tue, Nov 26, 2024 at 02:59:10PM +0800, Boshi Yu wrote:
> The address handle contains the necessary information to transmit
> messages to a remote peer in the RoCEv2 protocol. This commit
> implements the erdma_create_ah(), erdma_destroy_ah(), and
> erdma_query_ah() interfaces, which are used to create, destroy,
> and query an address handle, respectively.
> 
> Signed-off-by: Boshi Yu <boshiyu@linux.alibaba.com>
> Reviewed-by: Cheng Xu <chengyou@linux.alibaba.com>
> ---
>  drivers/infiniband/hw/erdma/erdma.h       |   4 +-
>  drivers/infiniband/hw/erdma/erdma_hw.h    |  34 ++++++
>  drivers/infiniband/hw/erdma/erdma_main.c  |   4 +
>  drivers/infiniband/hw/erdma/erdma_verbs.c | 135 +++++++++++++++++++++-
>  drivers/infiniband/hw/erdma/erdma_verbs.h |  28 +++++
>  5 files changed, 203 insertions(+), 2 deletions(-)

<...>

> +static void erdma_av_to_attr(struct erdma_av *av, struct rdma_ah_attr *attr)
> +{
> +	attr->type = RDMA_AH_ATTR_TYPE_ROCE;
> +
> +	rdma_ah_set_sl(attr, av->sl);
> +	rdma_ah_set_port_num(attr, av->port);
> +	rdma_ah_set_ah_flags(attr, IB_AH_GRH);
> +
> +	rdma_ah_set_grh(attr, NULL, av->flow_label, av->sgid_index,
> +			av->hop_limit, av->traffic_class);
> +	rdma_ah_set_dgid_raw(attr, av->dgid);
> +}

<...>

> +int erdma_query_ah(struct ib_ah *ibah, struct rdma_ah_attr *ah_attr)
> +{
> +	struct erdma_ah *ah = to_eah(ibah);
> +
> +	memset(ah_attr, 0, sizeof(*ah_attr));
> +	erdma_av_to_attr(&ah->av, ah_attr);

This function is used only once and in this file. There is no need to
create useless indirection. The same comment applicable to other
functions as well.

Thanks

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH for-next 1/8] RDMA/erdma: Probe the erdma RoCEv2 device
  2024-12-04 14:03   ` Leon Romanovsky
@ 2024-12-05  2:46     ` Boshi Yu
  0 siblings, 0 replies; 21+ messages in thread
From: Boshi Yu @ 2024-12-05  2:46 UTC (permalink / raw)
  To: Leon Romanovsky; +Cc: jgg, linux-rdma, kaishen, chengyou



在 2024/12/4 22:03, Leon Romanovsky 写道:
> On Tue, Nov 26, 2024 at 02:59:07PM +0800, Boshi Yu wrote:
>> Currently, the erdma driver supports both the iWARP and RoCEv2 protocols.
>> The erdma driver reads the ERDMA_REGS_DEV_PROTO_REG register to identify
>> the protocol used by the erdma device. Since each protocol requires
>> different ib_device_ops, we introduce the erdma_device_ops_iwarp and
>> erdma_device_ops_rocev2 for iWARP and RoCEv2 protocols, respectively.
>>
>> Signed-off-by: Boshi Yu <boshiyu@linux.alibaba.com>
>> Reviewed-by: Cheng Xu <chengyou@linux.alibaba.com>
>> ---
>>   drivers/infiniband/hw/erdma/Kconfig       |  2 +-
>>   drivers/infiniband/hw/erdma/erdma.h       |  3 +-
>>   drivers/infiniband/hw/erdma/erdma_hw.h    |  7 ++++
>>   drivers/infiniband/hw/erdma/erdma_main.c  | 47 ++++++++++++++++++-----
>>   drivers/infiniband/hw/erdma/erdma_verbs.c | 16 +++++++-
>>   drivers/infiniband/hw/erdma/erdma_verbs.h | 12 ++++++
>>   6 files changed, 75 insertions(+), 12 deletions(-)
> 
> <...>
> 
>> +++ b/drivers/infiniband/hw/erdma/erdma_main.c
>> @@ -172,6 +172,12 @@ static int erdma_device_init(struct erdma_dev *dev, struct pci_dev *pdev)
>>   {
>>   	int ret;
>>   
>> +	dev->proto = erdma_reg_read32(dev, ERDMA_REGS_DEV_PROTO_REG);
>> +	if (!erdma_device_iwarp(dev) && !erdma_device_rocev2(dev)) {
> 
> Why do you need this check? Your old driver which supports only iwarp
> doesn't have this check, so why did you suddenly need it for roce?
> 

Hi, Leon,

We initially try to avoid reading an invalid value from the hardware.
Thank you for your question; I found that the check is unnecessary since
the value of ERDMA_REGS_DEV_PROTO_REG can only be 0 or 1. We will remove
this check in patch v2.

Thanks,

Boshi Yu

>> +		dev_err(&pdev->dev, "Unsupported protocol: %d\n", dev->proto);
>> +		return -ENODEV;
>> +	}
>> +
> 
> Thanks


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH for-next 4/8] RDMA/erdma: Add address handle implementation
  2024-12-04 14:11   ` Leon Romanovsky
@ 2024-12-05  2:54     ` Boshi Yu
  0 siblings, 0 replies; 21+ messages in thread
From: Boshi Yu @ 2024-12-05  2:54 UTC (permalink / raw)
  To: Leon Romanovsky; +Cc: jgg, linux-rdma, kaishen, chengyou



On 2024/12/4 22:11, Leon Romanovsky wrote:
> On Tue, Nov 26, 2024 at 02:59:10PM +0800, Boshi Yu wrote:
>> The address handle contains the necessary information to transmit
>> messages to a remote peer in the RoCEv2 protocol. This commit
>> implements the erdma_create_ah(), erdma_destroy_ah(), and
>> erdma_query_ah() interfaces, which are used to create, destroy,
>> and query an address handle, respectively.
>>
>> Signed-off-by: Boshi Yu <boshiyu@linux.alibaba.com>
>> Reviewed-by: Cheng Xu <chengyou@linux.alibaba.com>
>> ---
>>   drivers/infiniband/hw/erdma/erdma.h       |   4 +-
>>   drivers/infiniband/hw/erdma/erdma_hw.h    |  34 ++++++
>>   drivers/infiniband/hw/erdma/erdma_main.c  |   4 +
>>   drivers/infiniband/hw/erdma/erdma_verbs.c | 135 +++++++++++++++++++++-
>>   drivers/infiniband/hw/erdma/erdma_verbs.h |  28 +++++
>>   5 files changed, 203 insertions(+), 2 deletions(-)
> 
> <...>
> 
>> +static void erdma_av_to_attr(struct erdma_av *av, struct rdma_ah_attr *attr)
>> +{
>> +	attr->type = RDMA_AH_ATTR_TYPE_ROCE;
>> +
>> +	rdma_ah_set_sl(attr, av->sl);
>> +	rdma_ah_set_port_num(attr, av->port);
>> +	rdma_ah_set_ah_flags(attr, IB_AH_GRH);
>> +
>> +	rdma_ah_set_grh(attr, NULL, av->flow_label, av->sgid_index,
>> +			av->hop_limit, av->traffic_class);
>> +	rdma_ah_set_dgid_raw(attr, av->dgid);
>> +}
> 
> <...>
> 
>> +int erdma_query_ah(struct ib_ah *ibah, struct rdma_ah_attr *ah_attr)
>> +{
>> +	struct erdma_ah *ah = to_eah(ibah);
>> +
>> +	memset(ah_attr, 0, sizeof(*ah_attr));
>> +	erdma_av_to_attr(&ah->av, ah_attr);
> 
> This function is used only once and in this file. There is no need to
> create useless indirection. The same comment applicable to other
> functions as well.
> 
> Thanks

Hi, Leon,

Thank you for your suggestion. We will fix the problem in the patch v2.

Thanks,
Boshi Yu



^ permalink raw reply	[flat|nested] 21+ messages in thread

end of thread, other threads:[~2024-12-05  2:54 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-11-26  6:59 [PATCH for-next 0/8] RDMA/erdma: Support the RoCEv2 protocol Boshi Yu
2024-11-26  6:59 ` [PATCH for-next 1/8] RDMA/erdma: Probe the erdma RoCEv2 device Boshi Yu
2024-11-26 15:36   ` Zhu Yanjun
2024-11-28  2:07     ` Cheng Xu
2024-11-28 13:07       ` Zhu Yanjun
2024-12-04 14:03   ` Leon Romanovsky
2024-12-05  2:46     ` Boshi Yu
2024-11-26  6:59 ` [PATCH for-next 2/8] RDMA/erdma: Add GID table management interfaces Boshi Yu
2024-11-26 15:51   ` Zhu Yanjun
2024-11-28  2:35     ` Boshi Yu
2024-11-29  8:54       ` Zhu Yanjun
2024-11-29 11:18         ` Boshi Yu
2024-11-29 18:40           ` Zhu Yanjun
2024-11-26  6:59 ` [PATCH for-next 3/8] RDMA/erdma: Add the erdma_query_pkey() interface Boshi Yu
2024-11-26  6:59 ` [PATCH for-next 4/8] RDMA/erdma: Add address handle implementation Boshi Yu
2024-12-04 14:11   ` Leon Romanovsky
2024-12-05  2:54     ` Boshi Yu
2024-11-26  6:59 ` [PATCH for-next 5/8] RDMA/erdma: Add erdma_modify_qp_rocev2() interface Boshi Yu
2024-11-26  6:59 ` [PATCH for-next 6/8] RDMA/erdma: Reformat the code of the modify_qp interface Boshi Yu
2024-11-26  6:59 ` [PATCH for-next 7/8] RDMA/erdma: Add the query_qp command to the cmdq Boshi Yu
2024-11-26  6:59 ` [PATCH for-next 8/8] RDMA/erdma: Support UD QPs and UD WRs Boshi Yu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox