Linux RDMA and InfiniBand development
 help / color / mirror / Atom feed
* [PATCH rdma v9 0/7] Add ZTE DingHai Ethernet Protocol Driver for RDMA
@ 2026-11-03 12:56 Yanze Zhang
  2026-11-03 12:56 ` [PATCH rdma v9 1/7] RDMA/zrdma: Add build infrastructure and module skeleton Yanze Zhang
                   ` (6 more replies)
  0 siblings, 7 replies; 15+ messages in thread
From: Yanze Zhang @ 2026-11-03 12:56 UTC (permalink / raw)
  To: jgg, leon, julianbraha, huangjunxian6, yanjun.zhu
  Cc: Markus.Elfring, lkp, linux-kernel, linux-rdma, wei.quan,
	han.junyang, ran.ming, han.chengfei, zhang.yanze

The ZTE DingHai (ZXDH) RDMA driver provides RoCEv2 support for ZTE DingHai
network adapters. It binds to the auxiliary device that the DingHai
Ethernet PF driver creates.

The PF driver is being merged through net-next: the first batch, which
introduces the DINGHAI and DINGHAI_PF Kconfig symbols and the
"dinghai10e" PF driver, is already in net-next [1], and the second batch
is still under review [2]. The patch that creates the auxiliary device
is still being prepared and has not been posted yet, so this series is
posted for review ahead of it and the driver does not probe on the
upstream baseline until it lands. The series is based on an rdma/for-next
baseline that already contains the first batch, so "depends on
DINGHAI_PF" resolves. The driver matches the auxiliary device by name
only, so it cannot bind to an unrelated PCI function.

This series covers the registration of the device, the device and the port
queries, the user context, the protection domains and the mapping of the
doorbell areas. The queue pair and completion queue data path is not part
of it and follows separately. Protection domains that the kernel
allocates are not supported either, because the driver does not provide
the memory registration of the core yet.

Testing: the driver builds, and every commit of the series was built on
its own to make sure that the series stays bisectable. The build was
tested with CONFIG_DINGHAI_PF=y, and the Kconfig dependency was
verified: with DINGHAI_PF disabled, the driver is not built at all.

The series was probed on DingHai hardware, with 'rdma link' /
'ibv_devinfo' enumerating the device. The hardware testing was done with
a PF driver that already creates the auxiliary device, because the
baseline that this series is based on only has the first batch, which
does not create it yet.

Two other points are noted for completeness. An __iomem annotation on
mem_rsrc is moot, since it is plain vzalloc'd memory rather than a BAR
mapping. Replacing the resource bitmaps with XArray/IDA is a cleanup
that does not change behaviour and will follow separately. Neither of
them affects probe/remove or the verbs that are implemented here.

Two review findings of the last round are deliberately not taken:

 - The module registration is kept as open coded init and exit
   functions, because the registration of the driver will grow more
   steps when the data path is added.
 - The structures of the auxiliary device are still in the private
   header of this driver. The DingHai PF driver does not create the
   auxiliary device yet, so the shared header between the two drivers
   will follow with the PF driver patch.

---
Changes in v9:
- The Kconfig depends on DINGHAI_PF instead of DINGHAI, because DINGHAI
  is only the boolean vendor guard and the PF driver is the one that
  creates the auxiliary device (Zhu Yanjun on v3).
- The declarations that were added and removed again within the series
  are gone, the auxiliary device names are used directly instead of
  macros, and so are the queue pair, completion queue and shared receive
  queue tables that were reserved in the resource memory but never used
  (Leon Romanovsky on v2, Sashiko on v8).
- The patches that introduced a piece of code now introduce it in its
  final form, so that the later patches only add to it and no patch
  rewrites what an earlier patch has added.
- The MTU is converted with ib_mtu_int_to_enum() of the core instead of
  a private copy of the same conversion (Sashiko on v8).
- The uverbs requests are validated with ib_copy_validate_udata_in() and
  the responses are copied with ib_respond_udata(), so that a truncated
  request is rejected and the trailing bytes of the response are zeroed
  (Sashiko on v8).
- The error messages that the user space can trigger are rate limited
  (Sashiko on v8).
- The MAINTAINERS entry covers the uapi header as well.
- Link to v8: https://lore.kernel.org/linux-rdma/20261102082026.2645777-1-zhang.yanze@zte.com.cn/

Changes in v8:
- The 8K index counter array is released with a cleared pointer on the
  probe error path, so that the dealloc hook does not free the same
  allocation twice.
- The number of completion vectors is no longer reported as zero.
- The driver info is read with the rtnl lock held unconditionally,
  because rtnl_is_locked() does not tell whether the current task holds
  it.
- The unused handler and name lists are gone.
- The device and port query operations moved ahead of the probe path,
  because ib_register_device() calls the query callbacks without
  checking them for NULL.
- Link to v7: https://lore.kernel.org/linux-rdma/20261027021119.2325798-1-zhang.yanze@zte.com.cn/

Changes in v7:
- Patch 2/7: the uapi header is tagged with the Linux-syscall-note SPDX
  identifier, which headers_install requires for a header that is
  installed to userspace.
- Patch 3/7: the name buffer length is passed to zxdh_get_del_rdma_name()
  and zxdh_free_rsrc() uses guard(spinlock_irqsave).
- Patch 4/7: zrdma_main.c is kept in place, because v6 removed it in the
  middle of the series, which broke both bisection and the build of that
  single commit.
- Patch 5/7: the device ops are installed right after ib_alloc_device(),
  so that the dealloc_driver hook is in place before any resource is
  taken.
- Patch 6/7: the SRQ doorbell offset is reported like the SQ and CQ
  doorbells, and the SRQ mapping covers the whole doorbell area on 16K
  and 64K page systems. The size handed to userspace is the very same
  length that is registered, otherwise rdma_user_mmap_entry_get()
  rejects the mmap.
- Patch 7/7: query_device() accepts a NULL udata, which is how the core
  calls it during registration; the number of send and receive SGEs is
  reported; the firmware version is parsed as unsigned values; the
  driver info is read with rtnl held; the port speed comes from
  ib_get_eth_speed() instead of a cached value that goes stale on a link
  change; the immutable port information is filled in directly, so that
  it does not depend on the port query running during the registration;
  the port number is passed to rdma_protocol_roce() instead of being
  hard coded; the query_gid callback is dropped, as the RoCE GID cache is
  owned by the core.
- Link to v6: https://lore.kernel.org/linux-rdma/20261024071539.2182864-1-zhang.yanze@zte.com.cn/

Changes in v6:
- Patch 1/7: the ineffective .driver.name indirection in
  auxiliary_driver is dropped.
- Patch 2/7: ZXDH_RDMA_TOOL_SHOW_RES_MAP is dropped, as bit 5 collides
  with ZXDH_RDMA_TOOL_CFG_DEV_PARAM; zrdma_abi.h moves to
  include/uapi/rdma/ and includes <linux/types.h>, so that userspace can
  use the ABI directly.
- Patch 5/7: .dealloc_driver is used for the probe/remove cleanup, the
  duplicate ib_register_device retry is dropped, the handler is published
  only after ib_register_device() succeeds, the common_func() result is
  taken as int, so that a negative errno is not mistaken for a
  capability, and max_ceqs is guarded against msix_count == 0.
- Patch 6/7: kvfree is used for the vzalloc'd regions, the PD allocation
  warning is rate limited, and the page-offset mask is applied to
  srq_db_bar_off like the SQ/CQ doorbells.
- Patch 7/7: rtnl_trylock is used when walking the bond's lower
  devices, the ethtool_ops NULL guard is added, sys_image_guid is built
  with addrconf_addr_eui48(), and extract_version() handles both the
  "E310-V25.30.103.01" and the "<ver> (<vendor>)" layouts.
- Link to v5: https://lore.kernel.org/linux-rdma/20260811093740.2607476-1-zhang.yanze@zte.com.cn/

Changes in v5:
- The driver is split into seven smaller, logically independent patches,
  each of them below 300 lines and independently compilable, as Leon
  Romanovsky asked for.
- The driver registers with a valid driver_id, so that it is functional
  and loads without errors, as Leon Romanovsky asked for.
- The Kconfig depends on PCI and NETDEVICES and selects AUXILIARY_BUS,
  as Zhu Yanjun suggested.
- The build error for the incomplete type 'struct msix_entry' is fixed
  by including <linux/msi.h> (kernel test robot).
- The unused defines, functions and dead code paths are removed, and all
  new files follow the kernel coding style (checkpatch.pl --strict).
- Link to v4: https://lore.kernel.org/linux-rdma/20260704082640.664061-1-zhang.yanze@zte.com.cn/

Changes in v4:
- Fixed Kconfig help text indentation (Julian Braha).
- Self-correction: Updated SPDX license tag and fixed Makefile
  indentation to strictly follow subsystem standards.
- Link to v3: https://lore.kernel.org/linux-rdma/20260702122256.569952-1-zhang.yanze@zte.com.cn/

Changes in v3:
- Fixed missing handle release in zxdh_remove() as pointed out by Junxian
  on v1.
- Removed outdated reference to "auxiliary bus following hns pattern" from
  cover letter description.
- Addressed Junxian's indentation concern on v1: verified code against
  checkpatch.pl --strict and confirmed 8-character indentation is used
  throughout.
- Link to v2: https://lore.kernel.org/linux-rdma/20260626165050955lBuUhmj0yLn5xCsQ-tbx4@zte.com.cn/

Changes in v2:
- Removed redundant 'depends on INFINIBAND' from Kconfig as it is already
  wrapped by the parent if-block (Julian Braha, v1 review).
- Link to v1: https://lore.kernel.org/linux-rdma/202606241644572798vwNbZEAtt3c2IHcJUtCs@zte.com.cn/

[1] https://lore.kernel.org/netdev/178598040988.599522.8462097247667886071.git-patchwork-notify@kernel.org/
[2] https://lore.kernel.org/netdev/20261014151200489685SCIlolykW0NGfL5EtQ@zte.com.cn/
---

Yanze Zhang (7):
  RDMA/zrdma: Add build infrastructure and module skeleton
  RDMA/zrdma: Add core data structures and ABI definitions
  RDMA/zrdma: Add internal headers and hardware register definitions
  RDMA/zrdma: Add hardware resource initialization and verbs skeleton
  RDMA/zrdma: Implement device and port query operations
  RDMA/zrdma: Add device probe and remove logic
  RDMA/zrdma: Implement context, PD, and mmap operations

 MAINTAINERS                               |   7 +
 drivers/infiniband/Kconfig                |   1 +
 drivers/infiniband/hw/Makefile            |   1 +
 drivers/infiniband/hw/zrdma/Kconfig       |  11 +
 drivers/infiniband/hw/zrdma/Makefile      |   7 +
 drivers/infiniband/hw/zrdma/zrdma_ctrl.h  |  20 +
 drivers/infiniband/hw/zrdma/zrdma_defs.h  |  19 +
 drivers/infiniband/hw/zrdma/zrdma_hw.c    | 118 ++++
 drivers/infiniband/hw/zrdma/zrdma_hw.h    |  21 +
 drivers/infiniband/hw/zrdma/zrdma_main.c  | 223 +++++++
 drivers/infiniband/hw/zrdma/zrdma_main.h  | 177 +++++
 drivers/infiniband/hw/zrdma/zrdma_type.h  |  92 +++
 drivers/infiniband/hw/zrdma/zrdma_verbs.c | 757 ++++++++++++++++++++++
 drivers/infiniband/hw/zrdma/zrdma_verbs.h | 119 ++++
 include/uapi/rdma/ib_user_ioctl_verbs.h   |   1 +
 include/uapi/rdma/zrdma_abi.h             | 114 ++++
 16 files changed, 1688 insertions(+)
 create mode 100644 drivers/infiniband/hw/zrdma/Kconfig
 create mode 100644 drivers/infiniband/hw/zrdma/Makefile
 create mode 100644 drivers/infiniband/hw/zrdma/zrdma_ctrl.h
 create mode 100644 drivers/infiniband/hw/zrdma/zrdma_defs.h
 create mode 100644 drivers/infiniband/hw/zrdma/zrdma_hw.c
 create mode 100644 drivers/infiniband/hw/zrdma/zrdma_hw.h
 create mode 100644 drivers/infiniband/hw/zrdma/zrdma_main.c
 create mode 100644 drivers/infiniband/hw/zrdma/zrdma_main.h
 create mode 100644 drivers/infiniband/hw/zrdma/zrdma_type.h
 create mode 100644 drivers/infiniband/hw/zrdma/zrdma_verbs.c
 create mode 100644 drivers/infiniband/hw/zrdma/zrdma_verbs.h
 create mode 100644 include/uapi/rdma/zrdma_abi.h


base-commit: c3e8e9451e6f1b69f685b75e0fbf14f3d0fb2539
-- 
2.43.5


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

* [PATCH rdma v9 1/7] RDMA/zrdma: Add build infrastructure and module skeleton
  2026-11-03 12:56 [PATCH rdma v9 0/7] Add ZTE DingHai Ethernet Protocol Driver for RDMA Yanze Zhang
@ 2026-11-03 12:56 ` Yanze Zhang
  2026-11-03 13:20   ` sashiko-bot
  2026-11-03 12:56 ` [PATCH rdma v9 2/7] RDMA/zrdma: Add core data structures and ABI definitions Yanze Zhang
                   ` (5 subsequent siblings)
  6 siblings, 1 reply; 15+ messages in thread
From: Yanze Zhang @ 2026-11-03 12:56 UTC (permalink / raw)
  To: jgg, leon, julianbraha, huangjunxian6, yanjun.zhu
  Cc: Markus.Elfring, lkp, linux-kernel, linux-rdma, wei.quan,
	han.junyang, ran.ming, han.chengfei, zhang.yanze

Add MAINTAINERS entry, Kconfig, and Makefile entries for the ZTE DingHai
RDMA driver. Include a minimal module skeleton with auxiliary driver
registration structure to ensure the build system works and the module
can be loaded.

The driver depends on DINGHAI_PF because it binds to the auxiliary
device that the DingHai PF driver creates. The DINGHAI_PF symbol is
already present in the rdma/for-next baseline this series is based on,
so the dependency resolves.

Signed-off-by: Yanze Zhang <zhang.yanze@zte.com.cn>
---
 MAINTAINERS                              |  7 +++
 drivers/infiniband/Kconfig               |  1 +
 drivers/infiniband/hw/Makefile           |  1 +
 drivers/infiniband/hw/zrdma/Kconfig      | 11 +++++
 drivers/infiniband/hw/zrdma/Makefile     |  4 ++
 drivers/infiniband/hw/zrdma/zrdma_main.c | 57 ++++++++++++++++++++++++
 include/uapi/rdma/ib_user_ioctl_verbs.h  |  1 +
 7 files changed, 82 insertions(+)
 create mode 100644 drivers/infiniband/hw/zrdma/Kconfig
 create mode 100644 drivers/infiniband/hw/zrdma/Makefile
 create mode 100644 drivers/infiniband/hw/zrdma/zrdma_main.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 2a6e6ec629e04..d560ddad47fe2 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -30193,6 +30193,13 @@ L:	netdev@vger.kernel.org
 S:	Maintained
 F:	drivers/net/ethernet/zte/
 
+ZTE DINGHAI ZRDMA DRIVER
+M:	Yanze Zhang <zhang.yanze@zte.com.cn>
+L:	linux-rdma@vger.kernel.org
+S:	Supported
+F:	drivers/infiniband/hw/zrdma/
+F:	include/uapi/rdma/zrdma_abi.h
+
 THE REST
 M:	Linus Torvalds <torvalds@linux-foundation.org>
 L:	linux-kernel@vger.kernel.org
diff --git a/drivers/infiniband/Kconfig b/drivers/infiniband/Kconfig
index 086195758a8ac..419dbf742f387 100644
--- a/drivers/infiniband/Kconfig
+++ b/drivers/infiniband/Kconfig
@@ -100,6 +100,7 @@ source "drivers/infiniband/hw/ocrdma/Kconfig"
 source "drivers/infiniband/hw/qedr/Kconfig"
 source "drivers/infiniband/hw/usnic/Kconfig"
 source "drivers/infiniband/hw/vmw_pvrdma/Kconfig"
+source "drivers/infiniband/hw/zrdma/Kconfig"
 source "drivers/infiniband/sw/rdmavt/Kconfig"
 endif # !UML
 source "drivers/infiniband/sw/rxe/Kconfig"
diff --git a/drivers/infiniband/hw/Makefile b/drivers/infiniband/hw/Makefile
index c42b22ac3303d..a86b867c56d49 100644
--- a/drivers/infiniband/hw/Makefile
+++ b/drivers/infiniband/hw/Makefile
@@ -16,3 +16,4 @@ obj-$(CONFIG_INFINIBAND_BNXT_RE)	+= bnxt_re/
 obj-$(CONFIG_INFINIBAND_BNG_RE)		+= bng_re/
 obj-$(CONFIG_INFINIBAND_ERDMA)		+= erdma/
 obj-$(CONFIG_INFINIBAND_IONIC)		+= ionic/
+obj-$(CONFIG_INFINIBAND_ZRDMA)		+= zrdma/
diff --git a/drivers/infiniband/hw/zrdma/Kconfig b/drivers/infiniband/hw/zrdma/Kconfig
new file mode 100644
index 0000000000000..ba62dc8288aac
--- /dev/null
+++ b/drivers/infiniband/hw/zrdma/Kconfig
@@ -0,0 +1,11 @@
+# SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
+config INFINIBAND_ZRDMA
+	tristate "ZTE Ethernet Protocol Driver for RDMA"
+	depends on DINGHAI_PF
+	select AUXILIARY_BUS
+	help
+	  Say Y or M here to enable support for the ZTE DingHai (ZXDH) Ethernet
+	  Protocol Driver for RDMA. This driver provides RDMA over Converged
+	  Ethernet (RoCE) functionality for ZTE DingHai network adapters.
+	  If you choose to build this driver as a module, it will be built as
+	  a module named zrdma.
diff --git a/drivers/infiniband/hw/zrdma/Makefile b/drivers/infiniband/hw/zrdma/Makefile
new file mode 100644
index 0000000000000..2ddf50d1fd208
--- /dev/null
+++ b/drivers/infiniband/hw/zrdma/Makefile
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
+
+obj-$(CONFIG_INFINIBAND_ZRDMA) += zrdma.o
+zrdma-y := zrdma_main.o
diff --git a/drivers/infiniband/hw/zrdma/zrdma_main.c b/drivers/infiniband/hw/zrdma/zrdma_main.c
new file mode 100644
index 0000000000000..80856c7ff6b2a
--- /dev/null
+++ b/drivers/infiniband/hw/zrdma/zrdma_main.c
@@ -0,0 +1,57 @@
+// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
+/*
+ * ZTE DingHai Rdma driver
+ * Copyright (c) 2022-2026, ZTE Corporation
+ */
+
+#include <linux/module.h>
+#include <linux/auxiliary_bus.h>
+
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_AUTHOR("Yanze Zhang <zhang.yanze@zte.com.cn>");
+MODULE_DESCRIPTION("ZTE Ethernet Protocol Driver for RDMA");
+
+/* The name has to match the auxiliary device that the DingHai PF
+ * driver creates.
+ */
+static const struct auxiliary_device_id zxdh_auxiliary_id_table[] = {
+	{
+		.name = "dinghai10e.rdma_aux",
+	},
+	{},
+};
+
+MODULE_DEVICE_TABLE(auxiliary, zxdh_auxiliary_id_table);
+
+static int zxdh_probe(struct auxiliary_device *aux_dev,
+		      const struct auxiliary_device_id *id)
+{
+	/* Placeholder: Real probe logic will be added in subsequent patches */
+	dev_info(&aux_dev->dev, "ZTE DingHai RDMA device detected (stub)\n");
+	return 0;
+}
+
+static void zxdh_remove(struct auxiliary_device *aux_dev)
+{
+	dev_info(&aux_dev->dev, "ZTE DingHai RDMA device removed (stub)\n");
+}
+
+static struct auxiliary_driver zxdh_auxiliary_drv = {
+	.name = "rdma_aux",
+	.id_table = zxdh_auxiliary_id_table,
+	.probe = zxdh_probe,
+	.remove = zxdh_remove,
+};
+
+static int __init zrdma_module_init(void)
+{
+	return auxiliary_driver_register(&zxdh_auxiliary_drv);
+}
+
+static void __exit zrdma_module_exit(void)
+{
+	auxiliary_driver_unregister(&zxdh_auxiliary_drv);
+}
+
+module_init(zrdma_module_init);
+module_exit(zrdma_module_exit);
diff --git a/include/uapi/rdma/ib_user_ioctl_verbs.h b/include/uapi/rdma/ib_user_ioctl_verbs.h
index 21f86cc7bb1f1..98dcea207357c 100644
--- a/include/uapi/rdma/ib_user_ioctl_verbs.h
+++ b/include/uapi/rdma/ib_user_ioctl_verbs.h
@@ -257,6 +257,7 @@ enum rdma_driver_id {
 	RDMA_DRIVER_ERDMA,
 	RDMA_DRIVER_MANA,
 	RDMA_DRIVER_IONIC,
+	RDMA_DRIVER_ZRDMA,
 };
 
 enum ib_uverbs_gid_type {
-- 
2.43.5


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

* [PATCH rdma v9 2/7] RDMA/zrdma: Add core data structures and ABI definitions
  2026-11-03 12:56 [PATCH rdma v9 0/7] Add ZTE DingHai Ethernet Protocol Driver for RDMA Yanze Zhang
  2026-11-03 12:56 ` [PATCH rdma v9 1/7] RDMA/zrdma: Add build infrastructure and module skeleton Yanze Zhang
@ 2026-11-03 12:56 ` Yanze Zhang
  2026-11-03 13:19   ` sashiko-bot
  2026-11-03 12:56 ` [PATCH rdma v9 3/7] RDMA/zrdma: Add internal headers and hardware register definitions Yanze Zhang
                   ` (4 subsequent siblings)
  6 siblings, 1 reply; 15+ messages in thread
From: Yanze Zhang @ 2026-11-03 12:56 UTC (permalink / raw)
  To: jgg, leon, julianbraha, huangjunxian6, yanjun.zhu
  Cc: Markus.Elfring, lkp, linux-kernel, linux-rdma, wei.quan,
	han.junyang, ran.ming, han.chengfei, zhang.yanze

Add fundamental data structures, hardware control structures, and
user-space ABI definitions required by the driver. These headers
provide the type definitions for the subsequent implementation patches.

The UAPI header is installed to userspace, so it carries the
Linux-syscall-note SPDX tag that headers_install requires for a
GPL-licensed UAPI header.

Signed-off-by: Yanze Zhang <zhang.yanze@zte.com.cn>
---
 drivers/infiniband/hw/zrdma/zrdma_ctrl.h |  20 ++++
 drivers/infiniband/hw/zrdma/zrdma_defs.h |  19 ++++
 drivers/infiniband/hw/zrdma/zrdma_type.h |  86 +++++++++++++++++
 include/uapi/rdma/zrdma_abi.h            | 114 +++++++++++++++++++++++
 4 files changed, 239 insertions(+)
 create mode 100644 drivers/infiniband/hw/zrdma/zrdma_ctrl.h
 create mode 100644 drivers/infiniband/hw/zrdma/zrdma_defs.h
 create mode 100644 drivers/infiniband/hw/zrdma/zrdma_type.h
 create mode 100644 include/uapi/rdma/zrdma_abi.h

diff --git a/drivers/infiniband/hw/zrdma/zrdma_ctrl.h b/drivers/infiniband/hw/zrdma/zrdma_ctrl.h
new file mode 100644
index 0000000000000..935b4cbd3e4a9
--- /dev/null
+++ b/drivers/infiniband/hw/zrdma/zrdma_ctrl.h
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
+ *
+ * ZTE DingHai Rdma driver
+ * Copyright (c) 2022-2026, ZTE Corporation
+ */
+
+#ifndef ZRDMA_CTRL_H
+#define ZRDMA_CTRL_H
+
+struct zxdh_hw {
+	struct device *device;
+};
+
+struct zxdh_sc_dev {
+	u32 max_ceqs;
+	u8 ep_id;
+	u8 driver_load;
+};
+
+#endif
diff --git a/drivers/infiniband/hw/zrdma/zrdma_defs.h b/drivers/infiniband/hw/zrdma/zrdma_defs.h
new file mode 100644
index 0000000000000..208f1f60bbaee
--- /dev/null
+++ b/drivers/infiniband/hw/zrdma/zrdma_defs.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
+ *
+ * ZTE DingHai Rdma driver
+ * Copyright (c) 2022-2026, ZTE Corporation
+ */
+
+#ifndef ZRDMA_DEFS_H
+#define ZRDMA_DEFS_H
+
+#include <linux/bitfield.h>
+#include <rdma/ib_verbs.h>
+
+#define ZXDH_FEATURE_RTS_AE 1ULL
+#define ZXDH_FEATURE_CQ_RESIZE 2ULL
+#define ZXDH_FEATURE_64_BYTE_CQE 128ULL
+
+#define ZXDH_MAX_USER_PRIORITY 8
+
+#endif /* ZRDMA_DEFS_H */
diff --git a/drivers/infiniband/hw/zrdma/zrdma_type.h b/drivers/infiniband/hw/zrdma/zrdma_type.h
new file mode 100644
index 0000000000000..ded4052453455
--- /dev/null
+++ b/drivers/infiniband/hw/zrdma/zrdma_type.h
@@ -0,0 +1,86 @@
+/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
+ *
+ * ZTE DingHai Rdma driver
+ * Copyright (c) 2022-2026, ZTE Corporation
+ */
+
+#ifndef ZRDMA_TYPE_H
+#define ZRDMA_TYPE_H
+
+#include <linux/auxiliary_bus.h>
+#include <linux/msi.h>
+
+enum zxdh_rdma_reset_type {
+	ZXDH_RDMA_PFR,
+	ZXDH_RDMA_CORER,
+	ZXDH_RDMA_GLOBR,
+};
+
+enum zxdh_function_type {
+	ZXDH_FUNCTION_TYPE_PF,
+	ZXDH_FUNCTION_TYPE_VF,
+};
+
+struct zxdh_rdma_core_dev;
+
+struct zxdh_rdma_core_ops {
+	int (*request_reset)(struct zxdh_rdma_core_dev *cdev,
+			     enum zxdh_rdma_reset_type reset_type);
+	int (*zxdh_common_func)(void *in_param, void *out_param, u32 opcode);
+};
+
+struct zxdh_rdma_ver_info {
+	u16 major;
+	u16 minor;
+	u64 support; /* 0~7:net_major,8~15:net_minor,16~23:rdma_minor,24~63:rscv */
+};
+
+enum zxdh_rdma_protocol {
+	ZXDH_RDMA_PROTOCOL_IWARP = BIT(0),
+	ZXDH_RDMA_PROTOCOL_ROCEV2 = BIT(1),
+};
+
+struct zxdh_qos_params {
+	u8 num_tc;
+};
+
+struct zxdh_rdma_core_dev {
+	struct pci_dev *pdev;
+	struct auxiliary_device *adev;
+	u8 __iomem *hw_addr;
+	int zdev_info_id;
+	struct zxdh_rdma_ver_info ver;
+	void *auxiliary_priv;
+	enum zxdh_function_type ftype;
+	u16 vport_id;
+	u16 slot_id;
+	enum zxdh_rdma_protocol rdma_protocol;
+
+	struct zxdh_qos_params qos_info;
+	struct msix_entry *msix_entries;
+	u16 msix_count;
+	const struct zxdh_rdma_core_ops *ops;
+	void *dh_dev;
+};
+
+struct zxdh_rdma_if {
+	void *(*get_rdma_netdev)(void *dh_dev);
+};
+
+struct zxdh_auxiliary_dev {
+	struct auxiliary_device adev;
+	struct zxdh_rdma_core_dev *zxdh_info;
+	struct zxdh_rdma_if *rdma_ops;
+	void *ops;
+	void *parent;
+	s32 aux_id;
+	void *auxiliary_ops[18];
+};
+
+struct zxdh_sc_pd {
+	struct zxdh_sc_dev *dev;
+	u32 pd_id;
+	int abi_ver;
+};
+
+#endif /* ZRDMA_TYPE_H */
diff --git a/include/uapi/rdma/zrdma_abi.h b/include/uapi/rdma/zrdma_abi.h
new file mode 100644
index 0000000000000..53f15591f894e
--- /dev/null
+++ b/include/uapi/rdma/zrdma_abi.h
@@ -0,0 +1,114 @@
+/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR Linux-OpenIB)
+ *
+ * ZTE DingHai Rdma driver
+ * Copyright (c) 2022-2026, ZTE Corporation
+ */
+
+#ifndef ZRDMA_ABI_H
+#define ZRDMA_ABI_H
+
+#include <linux/types.h>
+
+/* The version of the user space ABI that this driver implements. It is
+ * reported to the core as the uverbs ABI version of the device.
+ */
+#define ZXDH_ABI_VER 5
+
+/* The versions of the context that the user space can ask for with
+ * struct zxdh_alloc_ucontext_req.userspace_ver. A version tells the
+ * driver which features of the user space are available.
+ */
+#define ZXDH_CONTEXT_VER_V1 5
+#define ZXDH_CONTEXT_VER_V2 6
+#define ZXDH_CONTEXT_VER_V3 7
+
+enum zxdh_rdma_tool_flags {
+	ZXDH_QP_EXTEND_OP = 1 << 0,
+	ZXDH_CAPTURE = 1 << 1,
+	ZXDH_GET_HW_DATA = 1 << 2,
+	ZXDH_GET_HW_OBJECT_DATA = 1 << 3,
+	ZXDH_CHECK_HW_HEALTH = 1 << 4,
+	ZXDH_RDMA_TOOL_CFG_DEV_PARAM = 1 << 5,
+	ZXDH_RDMA_TOOL_READ_RAM = 1 << 6,
+	ZXDH_RDMA_TOOL_DEVX_MODIFY_CQ = 1 << 7,
+	ZXDH_RDMA_SET_CREDIT_CAP = 1 << 8,
+	ZXDH_RDMA_SWITCH = 1 << 9,
+	ZXDH_RDMA_TOOL_DEVX_EXT_MEM = 1 << 10,
+	ZXDH_RDMA_TOOL_PRIV_EXT = 1 << 11,
+	ZXDH_RDMA_TOOL_IOVA_CAP = 1 << 12,
+};
+
+enum zxdh_db_addr_type {
+	ZXDH_DB_ADDR_PHY = 0,
+	ZXDH_DB_ADDR_BAR = 1,
+};
+
+/* Request of the uverbs command INFINIBAND_UVERBS_CMD_ALLOC_CONTEXT. */
+struct zxdh_alloc_ucontext_req {
+	__u32 rsvd32;
+	/* Version of the user space, one of the ZXDH_CONTEXT_VER_*. */
+	__u8 userspace_ver;
+	__u8 rsvd8[3];
+};
+
+/* Response of the uverbs command INFINIBAND_UVERBS_CMD_ALLOC_CONTEXT. */
+struct zxdh_alloc_ucontext_resp {
+	/* Number of protection domains that the user space can create. */
+	__u32 max_pds;
+	/* Number of queue pairs that the user space can create. */
+	__u32 max_qps;
+	/* Size of the work queues (SQ+RQ) in the mmaped area. */
+	__u32 wq_size;
+	/* Version of the driver that created the context. */
+	__u8 kernel_ver;
+	/* Type of the address that a doorbell is written to, one of the
+	 * enum zxdh_db_addr_type.
+	 */
+	__u8 db_addr_type;
+	/* The RDMA tool features that the driver supports, one of the
+	 * enum zxdh_rdma_tool_flags.
+	 */
+	__u16 rdma_tool_flags;
+	/* The features that the driver supports. */
+	__aligned_u64 feature_flags;
+	/* The keys of the mappings of the doorbell areas. The user space
+	 * passes a key to mmap() to get the address of a doorbell.
+	 */
+	__aligned_u64 sq_db_mmap_key;
+	__aligned_u64 cq_db_mmap_key;
+	/* The limits of the work queue entries. */
+	__u32 max_hw_wq_frags;
+	__u32 max_hw_read_sges;
+	__u32 max_hw_inline;
+	__u32 max_hw_rq_quanta;
+	__u32 max_hw_srq_quanta;
+	__u32 max_hw_wq_quanta;
+	__u32 max_hw_srq_wr;
+	__u32 min_hw_cq_size;
+	__u32 max_hw_cq_size;
+	__u16 max_hw_sq_chunk;
+	/* The revision of the hardware and of the chip. */
+	__u8 hw_rev;
+	__u8 chip_rev;
+	__aligned_u64 srq_db_mmap_key;
+	/* The offset of the doorbell area in the page that is mapped. */
+	__aligned_u64 sq_db_bar_off;
+	__aligned_u64 cq_db_bar_off;
+	__aligned_u64 srq_db_bar_off;
+	/*
+	 * Size of the mapped SRQ doorbell area. The V1 and V2 contexts do
+	 * not have this field, so only the first page of the area is mapped
+	 * for them and they must not access beyond it.
+	 */
+	__u32 srq_db_mmap_size;
+	__u16 rsv[6];
+};
+
+/* Response of the uverbs command INFINIBAND_UVERBS_CMD_ALLOC_PD. */
+struct zxdh_alloc_pd_resp {
+	/* The identifier of the protection domain. */
+	__u32 pd_id;
+	__u8 rsvd[4];
+};
+
+#endif /* ZRDMA_ABI_H */
-- 
2.43.5


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

* [PATCH rdma v9 3/7] RDMA/zrdma: Add internal headers and hardware register definitions
  2026-11-03 12:56 [PATCH rdma v9 0/7] Add ZTE DingHai Ethernet Protocol Driver for RDMA Yanze Zhang
  2026-11-03 12:56 ` [PATCH rdma v9 1/7] RDMA/zrdma: Add build infrastructure and module skeleton Yanze Zhang
  2026-11-03 12:56 ` [PATCH rdma v9 2/7] RDMA/zrdma: Add core data structures and ABI definitions Yanze Zhang
@ 2026-11-03 12:56 ` Yanze Zhang
  2026-11-03 13:18   ` sashiko-bot
  2026-11-03 12:56 ` [PATCH rdma v9 4/7] RDMA/zrdma: Add hardware resource initialization and verbs skeleton Yanze Zhang
                   ` (3 subsequent siblings)
  6 siblings, 1 reply; 15+ messages in thread
From: Yanze Zhang @ 2026-11-03 12:56 UTC (permalink / raw)
  To: jgg, leon, julianbraha, huangjunxian6, yanjun.zhu
  Cc: Markus.Elfring, lkp, linux-kernel, linux-rdma, wei.quan,
	han.junyang, ran.ming, han.chengfei, zhang.yanze

Add internal header files for main driver logic and hardware registers.
These headers define the structures and constants used by the subsequent
implementation patches.

Signed-off-by: Yanze Zhang <zhang.yanze@zte.com.cn>
---
 drivers/infiniband/hw/zrdma/zrdma_hw.h   |  21 +++
 drivers/infiniband/hw/zrdma/zrdma_main.h | 177 +++++++++++++++++++++++
 drivers/infiniband/hw/zrdma/zrdma_type.h |   6 +
 3 files changed, 204 insertions(+)
 create mode 100644 drivers/infiniband/hw/zrdma/zrdma_hw.h
 create mode 100644 drivers/infiniband/hw/zrdma/zrdma_main.h

diff --git a/drivers/infiniband/hw/zrdma/zrdma_hw.h b/drivers/infiniband/hw/zrdma/zrdma_hw.h
new file mode 100644
index 0000000000000..16c5041ac0757
--- /dev/null
+++ b/drivers/infiniband/hw/zrdma/zrdma_hw.h
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
+ *
+ * ZTE DingHai Rdma driver
+ * Copyright (c) 2022-2026, ZTE Corporation
+ */
+
+#ifndef ZRDMA_HW_H
+#define ZRDMA_HW_H
+#include "zrdma_main.h"
+
+#define ZXDH_MAX_CQE 0x200000
+#define ZXDH_MAX_QP 0x4000
+#define ZXDH_MAX_MR 0x10000
+#define ZXDH_MAX_CQ 0x4000
+#define ZXDH_MAX_SRQ 0x2000
+#define ZXDH_MAX_PD 0x100000
+#define ZXDH_MAX_AH 0x10000
+#define ZXDH_MAX_MCG 0x4000
+#define ZXDH_MAX_8K_IDX 0x1c0
+
+#endif /* ZRDMA_HW_H */
diff --git a/drivers/infiniband/hw/zrdma/zrdma_main.h b/drivers/infiniband/hw/zrdma/zrdma_main.h
new file mode 100644
index 0000000000000..d65811735e74e
--- /dev/null
+++ b/drivers/infiniband/hw/zrdma/zrdma_main.h
@@ -0,0 +1,177 @@
+/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
+ *
+ * ZTE DingHai Rdma driver
+ * Copyright (c) 2022-2026, ZTE Corporation
+ */
+
+#ifndef ZRDMA_MAIN_H
+#define ZRDMA_MAIN_H
+
+#include <linux/auxiliary_bus.h>
+#include <linux/bitfield.h>
+#include <linux/cleanup.h>
+#include <linux/pci.h>
+#include <linux/spinlock.h>
+#include <rdma/ib_user_verbs.h>
+#include <rdma/ib_verbs.h>
+#include <rdma/zrdma_abi.h>
+#include <net/addrconf.h>
+
+#include "zrdma_type.h"
+#include "zrdma_ctrl.h"
+#include "zrdma_defs.h"
+
+#define ZXDH_FUNC_TYPE(vport_id) (((vport_id) >> 11) & 0x1)
+#define ZXDH_PF_ID(vport_id) (((vport_id) >> 8) & 0x7)
+#define ZXDH_EP_ID(vport_id) (((vport_id) >> 12) & 0x7)
+
+#define ZXDH_RST_TIMEOUT_HZ 4
+
+#define ZXDH_RDMA_COMMON_FUNC_CAP 1
+#define ZXDH_RDMA_COMM_FUNC BIT_ULL(24)
+
+extern const struct ib_device_ops zxdh_dev_ops;
+
+struct zxdh_pci_f;
+
+enum zxdh_func_type {
+	ZXDH_FUNC_NUM_REQUIRE = 0,
+	ZXDH_FUNC_IRQ_FREE = 3,
+};
+
+enum init_completion_state {
+	INVALID_STATE = 0,
+	INITIAL_STATE,
+};
+
+enum zxdh_rdma_vers {
+	ZXDH_GEN_2,
+};
+
+struct zxdh_gen_ops {
+	int (*zxdh_common_func)(void *in_param, void *out_param, u32 opcode);
+};
+
+struct zxdh_pci_f {
+	u8 ftype : 1;
+	u8 *mem_rsrc;
+	u8 rdma_ver;
+	u8 rst_to;
+	u8 pf_id;
+	u8 ep_id;
+	u32 msix_count;
+	u32 max_mr;
+	u32 max_qp;
+	u32 max_cq;
+	u32 max_ah;
+	u32 max_mcg;
+	u32 max_pd;
+	u32 next_pd;
+	u32 max_cqe;
+	u32 max_srq;
+	u32 max_pri;
+	u16 max_8k_idx;
+	u32 *qp_cnt_8k_idxs;
+	u32 ceqs_count;
+
+	unsigned long *allocated_qps;
+	unsigned long *allocated_cqs;
+	unsigned long *allocated_mrs;
+	unsigned long *allocated_pds;
+	unsigned long *allocated_mcgs;
+	unsigned long *allocated_ahs;
+	unsigned long *allocated_srqs;
+	unsigned long *allocated_pris;
+	unsigned long *allocated_8k_idx;
+
+	struct zxdh_sc_dev sc_dev;
+	struct pci_dev *pcidev;
+	struct zxdh_rdma_core_dev *zdev_info;
+	struct zxdh_hw hw;
+
+	spinlock_t rsrc_lock; /* protects resource allocation arrays */
+
+	struct msix_entry *msix_entries;
+	struct zxdh_gen_ops gen_ops;
+	struct zxdh_device *zdev;
+	u16 qp_index;
+	bool net_irq_cap;
+	int common_func_num_max;
+	void *dh_dev;
+};
+
+struct zxdh_device {
+	struct ib_device ibdev;
+	struct zxdh_pci_f *rf;
+	struct net_device *netdev;
+	struct list_head ah_list;
+	struct mutex ah_list_lock; /* protects ah_list operations */
+	u8 ibdev_status;
+	u8 roce_mode : 1;
+	enum init_completion_state init_state;
+	struct zxdh_auxiliary_dev *zxdh_adev;
+	atomic_t tx_port_affinity;
+	atomic_t sport_counter;
+};
+
+static inline struct zxdh_device *to_zdev(struct ib_device *ibdev)
+{
+	return container_of(ibdev, struct zxdh_device, ibdev);
+}
+
+static inline int zxdh_alloc_rsrc(struct zxdh_pci_f *rf,
+				  unsigned long *rsrc_array, u32 max_rsrc,
+				  u32 *req_rsrc_num, u32 *next,
+				  const char *rsrc_name)
+{
+	u32 rsrc_num;
+	int ret;
+
+	/* The pool is searched and the resource is taken under the lock, so
+	 * that two callers cannot pick the same resource. The lock is
+	 * taken with a guard, so that it is released on every exit path.
+	 * The exhaustion log is printed once the lock is released again,
+	 * because printk must not run while a spinlock is held.
+	 *
+	 * The search starts at the position after the last allocation, so
+	 * that the resources are handed out in turn. After the wrap-around
+	 * the position points after the last allocation again, which
+	 * affects the order of the allocations only.
+	 */
+	{
+		guard(spinlock_irqsave)(&rf->rsrc_lock);
+
+		rsrc_num = find_next_zero_bit(rsrc_array, max_rsrc, *next);
+		if (rsrc_num >= max_rsrc)
+			rsrc_num = find_first_zero_bit(rsrc_array, max_rsrc);
+		if (rsrc_num < max_rsrc) {
+			__set_bit(rsrc_num, rsrc_array);
+			*next = rsrc_num + 1;
+			if (*next == max_rsrc)
+				*next = 0;
+			*req_rsrc_num = rsrc_num;
+			ret = 0;
+		} else {
+			ret = -EOVERFLOW;
+		}
+	}
+
+	if (ret)
+		pr_err("zrdma: %s pool exhausted (capacity %u)\n",
+		       rsrc_name, max_rsrc);
+
+	return ret;
+}
+
+static inline void zxdh_free_rsrc(struct zxdh_pci_f *rf,
+				  unsigned long *rsrc_array, u32 rsrc_num)
+{
+	guard(spinlock_irqsave)(&rf->rsrc_lock);
+
+	__clear_bit(rsrc_num, rsrc_array);
+}
+
+int zxdh_ctrl_init_hw(struct zxdh_pci_f *rf);
+int zxdh_ib_register_device(struct zxdh_device *zdev);
+
+#endif /* ZRDMA_MAIN_H */
diff --git a/drivers/infiniband/hw/zrdma/zrdma_type.h b/drivers/infiniband/hw/zrdma/zrdma_type.h
index ded4052453455..c6ad2be17c159 100644
--- a/drivers/infiniband/hw/zrdma/zrdma_type.h
+++ b/drivers/infiniband/hw/zrdma/zrdma_type.h
@@ -21,6 +21,12 @@ enum zxdh_function_type {
 	ZXDH_FUNCTION_TYPE_VF,
 };
 
+/*
+ * The structures below describe the auxiliary device of the DingHai PF
+ * driver. Their layout has to match the definition of the PF driver
+ * exactly, because the probe path reads them through the auxiliary device
+ * that the PF driver provides.
+ */
 struct zxdh_rdma_core_dev;
 
 struct zxdh_rdma_core_ops {
-- 
2.43.5


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

* [PATCH rdma v9 4/7] RDMA/zrdma: Add hardware resource initialization and verbs skeleton
  2026-11-03 12:56 [PATCH rdma v9 0/7] Add ZTE DingHai Ethernet Protocol Driver for RDMA Yanze Zhang
                   ` (2 preceding siblings ...)
  2026-11-03 12:56 ` [PATCH rdma v9 3/7] RDMA/zrdma: Add internal headers and hardware register definitions Yanze Zhang
@ 2026-11-03 12:56 ` Yanze Zhang
  2026-11-03 13:21   ` sashiko-bot
  2026-11-03 12:56 ` [PATCH rdma v9 5/7] RDMA/zrdma: Implement device and port query operations Yanze Zhang
                   ` (2 subsequent siblings)
  6 siblings, 1 reply; 15+ messages in thread
From: Yanze Zhang @ 2026-11-03 12:56 UTC (permalink / raw)
  To: jgg, leon, julianbraha, huangjunxian6, yanjun.zhu
  Cc: Markus.Elfring, lkp, linux-kernel, linux-rdma, wei.quan,
	han.junyang, ran.ming, han.chengfei, zhang.yanze

Implement hardware resource initialization logic and provide a minimal
but functional verbs layer skeleton. This includes basic device
registration with the minimal set of device ops (owner, driver_id,
uverbs_abi_ver), to satisfy the requirement that the driver must be
functional and have a valid driver ID.

The hardware resources of the driver are held in a single allocation,
which carries the allocation bitmaps of the resource pools. The first
entry of the memory region, protection domain, queue pair, address
handle and multicast group pools is reserved.

The device ops are exported so that the probe path can install them
right after ib_alloc_device(). When the resource memory cannot be
allocated, the 8K index counter array is released with a cleared
pointer, so that the dealloc hook does not free the same allocation
twice.

Signed-off-by: Yanze Zhang <zhang.yanze@zte.com.cn>
---
 drivers/infiniband/hw/zrdma/Makefile      |   5 +-
 drivers/infiniband/hw/zrdma/zrdma_hw.c    | 118 +++++++++++++++++++++
 drivers/infiniband/hw/zrdma/zrdma_verbs.c |  50 +++++++++
 drivers/infiniband/hw/zrdma/zrdma_verbs.h | 119 ++++++++++++++++++++++
 4 files changed, 291 insertions(+), 1 deletion(-)
 create mode 100644 drivers/infiniband/hw/zrdma/zrdma_hw.c
 create mode 100644 drivers/infiniband/hw/zrdma/zrdma_verbs.c
 create mode 100644 drivers/infiniband/hw/zrdma/zrdma_verbs.h

diff --git a/drivers/infiniband/hw/zrdma/Makefile b/drivers/infiniband/hw/zrdma/Makefile
index 2ddf50d1fd208..9bc3650a8f2a9 100644
--- a/drivers/infiniband/hw/zrdma/Makefile
+++ b/drivers/infiniband/hw/zrdma/Makefile
@@ -1,4 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
 
 obj-$(CONFIG_INFINIBAND_ZRDMA) += zrdma.o
-zrdma-y := zrdma_main.o
+zrdma-y := \
+	zrdma_main.o \
+	zrdma_hw.o \
+	zrdma_verbs.o
diff --git a/drivers/infiniband/hw/zrdma/zrdma_hw.c b/drivers/infiniband/hw/zrdma/zrdma_hw.c
new file mode 100644
index 0000000000000..ba0e5760b52ca
--- /dev/null
+++ b/drivers/infiniband/hw/zrdma/zrdma_hw.c
@@ -0,0 +1,118 @@
+// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
+/*
+ * ZTE DingHai Rdma driver
+ * Copyright (c) 2022-2026, ZTE Corporation
+ */
+
+#include <linux/vmalloc.h>
+#include "zrdma_hw.h"
+#include "zrdma_ctrl.h"
+#include "zrdma_main.h"
+
+static void zxdh_set_hw_rsrc(struct zxdh_pci_f *rf)
+{
+	/* The layout is walked with a byte pointer, so that every step
+	 * matches the size that zxdh_calc_mem_rsrc_size() accounted for.
+	 * Both functions use the same order of the resources.
+	 */
+	u8 *ptr = rf->mem_rsrc;
+
+	rf->allocated_srqs = (unsigned long *)ptr;
+	ptr += sizeof(unsigned long) * BITS_TO_LONGS(rf->max_srq);
+	rf->allocated_qps = (unsigned long *)ptr;
+	ptr += sizeof(unsigned long) * BITS_TO_LONGS(rf->max_qp);
+	rf->allocated_cqs = (unsigned long *)ptr;
+	ptr += sizeof(unsigned long) * BITS_TO_LONGS(rf->max_cq);
+	rf->allocated_mrs = (unsigned long *)ptr;
+	ptr += sizeof(unsigned long) * BITS_TO_LONGS(rf->max_mr);
+	rf->allocated_pds = (unsigned long *)ptr;
+	ptr += sizeof(unsigned long) * BITS_TO_LONGS(rf->max_pd);
+	rf->allocated_ahs = (unsigned long *)ptr;
+	ptr += sizeof(unsigned long) * BITS_TO_LONGS(rf->max_ah);
+	rf->allocated_mcgs = (unsigned long *)ptr;
+	ptr += sizeof(unsigned long) * BITS_TO_LONGS(rf->max_mcg);
+	rf->allocated_pris = (unsigned long *)ptr;
+	ptr += sizeof(unsigned long) * BITS_TO_LONGS(rf->max_pri);
+	rf->allocated_8k_idx = (unsigned long *)ptr;
+	ptr += sizeof(unsigned long) * BITS_TO_LONGS(rf->max_8k_idx);
+
+	spin_lock_init(&rf->rsrc_lock);
+}
+
+static u32 zxdh_calc_mem_rsrc_size(struct zxdh_pci_f *rf)
+{
+	u32 rsrc_size;
+
+	rsrc_size = sizeof(unsigned long) * BITS_TO_LONGS(rf->max_srq);
+	rsrc_size += sizeof(unsigned long) * BITS_TO_LONGS(rf->max_qp);
+	rsrc_size += sizeof(unsigned long) * BITS_TO_LONGS(rf->max_cq);
+	rsrc_size += sizeof(unsigned long) * BITS_TO_LONGS(rf->max_mr);
+	rsrc_size += sizeof(unsigned long) * BITS_TO_LONGS(rf->max_pd);
+	rsrc_size += sizeof(unsigned long) * BITS_TO_LONGS(rf->max_ah);
+	rsrc_size += sizeof(unsigned long) * BITS_TO_LONGS(rf->max_mcg);
+	rsrc_size += sizeof(unsigned long) * BITS_TO_LONGS(rf->max_pri);
+	rsrc_size += sizeof(unsigned long) * BITS_TO_LONGS(rf->max_8k_idx);
+
+	return rsrc_size;
+}
+
+static int zxdh_initialize_hw_rsrc(struct zxdh_pci_f *rf)
+{
+	u32 rsrc_size;
+	int ret;
+
+	rf->max_cqe = ZXDH_MAX_CQE;
+	rf->max_qp = ZXDH_MAX_QP;
+	rf->max_mr = ZXDH_MAX_MR;
+	rf->max_cq = ZXDH_MAX_CQ;
+	rf->max_srq = ZXDH_MAX_SRQ;
+	rf->max_pd = ZXDH_MAX_PD;
+	rf->max_ah = ZXDH_MAX_AH;
+	rf->max_mcg = ZXDH_MAX_MCG;
+	rf->max_pri = ZXDH_MAX_USER_PRIORITY;
+	rf->max_8k_idx = ZXDH_MAX_8K_IDX;
+
+	rf->qp_cnt_8k_idxs = vzalloc(rf->max_8k_idx * sizeof(u32));
+	if (!rf->qp_cnt_8k_idxs) {
+		ret = -ENOMEM;
+		goto mem_8k_qp_cnt_vmalloc_fail;
+	}
+
+	rsrc_size = zxdh_calc_mem_rsrc_size(rf);
+	rf->mem_rsrc = vzalloc(rsrc_size);
+	if (!rf->mem_rsrc) {
+		ret = -ENOMEM;
+		goto mem_rsrc_vmalloc_fail;
+	}
+
+	zxdh_set_hw_rsrc(rf);
+
+	/* The first entry of the pools that are already in use is
+	 * reserved, so that a resource number of zero is not handed out.
+	 * The pools of the completion queues, the shared receive queues,
+	 * the user priorities and the 8K indices do not reserve an entry
+	 * yet, they are not allocated from yet.
+	 */
+	set_bit(0, rf->allocated_mrs);
+	set_bit(1, rf->allocated_mrs);
+	set_bit(0, rf->allocated_pds);
+	set_bit(0, rf->allocated_qps);
+	set_bit(0, rf->allocated_ahs);
+	set_bit(0, rf->allocated_mcgs);
+
+	return 0;
+
+mem_rsrc_vmalloc_fail:
+	vfree(rf->qp_cnt_8k_idxs);
+	/* Clear the pointer, the dealloc hook releases the very same
+	 * allocation again when the probe path unwinds.
+	 */
+	rf->qp_cnt_8k_idxs = NULL;
+mem_8k_qp_cnt_vmalloc_fail:
+	return ret;
+}
+
+int zxdh_ctrl_init_hw(struct zxdh_pci_f *rf)
+{
+	return zxdh_initialize_hw_rsrc(rf);
+}
diff --git a/drivers/infiniband/hw/zrdma/zrdma_verbs.c b/drivers/infiniband/hw/zrdma/zrdma_verbs.c
new file mode 100644
index 0000000000000..84ee7be418139
--- /dev/null
+++ b/drivers/infiniband/hw/zrdma/zrdma_verbs.c
@@ -0,0 +1,50 @@
+// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
+/*
+ * ZTE DingHai Rdma driver
+ * Copyright (c) 2022-2026, ZTE Corporation
+ */
+
+#include "zrdma_main.h"
+#include "zrdma_verbs.h"
+#include "zrdma_ctrl.h"
+
+static int zxdh_init_rdma_device(struct zxdh_device *zdev)
+{
+	struct pci_dev *pcidev = zdev->rf->pcidev;
+
+	zdev->ibdev.phys_port_cnt = 1;
+	/* The core divides by num_comp_vectors in ib_cq_pool_get() and
+	 * rejects every uverbs CQ creation when it is zero, so the count
+	 * is never allowed to drop below one.
+	 */
+	zdev->ibdev.num_comp_vectors = max_t(u32, zdev->rf->ceqs_count, 1);
+	zdev->ibdev.dev.parent = &pcidev->dev;
+
+	return 0;
+}
+
+int zxdh_ib_register_device(struct zxdh_device *zdev)
+{
+	int ret;
+
+	ret = zxdh_init_rdma_device(zdev);
+	if (ret)
+		return ret;
+
+	ret = ib_register_device(&zdev->ibdev, "zrdma%d", zdev->rf->hw.device);
+	if (ret)
+		goto error;
+
+	return 0;
+
+error:
+	pr_err("zrdma: Register RDMA device fail, ret=%d\n", ret);
+
+	return ret;
+}
+
+const struct ib_device_ops zxdh_dev_ops = {
+	.owner = THIS_MODULE,
+	.driver_id = RDMA_DRIVER_ZRDMA,
+	.uverbs_abi_ver = ZXDH_ABI_VER,
+};
diff --git a/drivers/infiniband/hw/zrdma/zrdma_verbs.h b/drivers/infiniband/hw/zrdma/zrdma_verbs.h
new file mode 100644
index 0000000000000..a435891ab7cf5
--- /dev/null
+++ b/drivers/infiniband/hw/zrdma/zrdma_verbs.h
@@ -0,0 +1,119 @@
+/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
+ *
+ * ZTE DingHai Rdma driver
+ * Copyright (c) 2022-2026, ZTE Corporation
+ */
+
+#ifndef ZRDMA_VERBS_H
+#define ZRDMA_VERBS_H
+
+#include <rdma/ib_umem.h>
+#include <rdma/ib_verbs.h>
+#include <rdma/uverbs_ioctl.h>
+
+#define CHIP_VERSION 1
+#define ZXDH_PAGE_OFFSET_NUM (PAGE_SIZE - 1)
+#define MAX_HW_WQ_FRAGS 15
+#define MAX_HW_READ_SGES 15
+#define MAX_HW_INLINE 217
+#define MAX_HW_SRQ_WR 15
+#define MAX_HW_RQ_QUANTA 15
+#define MAX_HW_SRQ_QUANTA 15
+#define MAX_HW_WQ_QUANTA 15
+#define MAX_HW_SQ_CHUNK 0x8000
+#define MAX_HW_CQ_SIZE 0x200000
+#define MIN_HW_CQ_SIZE 4
+
+#define ZXDH_MTU_HEADER_RSV 102
+
+#define ZXDH_PKEY_TBL_SZ 1
+#define ZXDH_GID_TBL_LEN 255
+#define ZXDH_DEFAULT_PKEY 0xFFFF
+
+#define SQ_DB_BAR_OFF 0x4c000
+#define CQ_DB_BAR_OFF 0x43000
+#define SRQ_DB_MMAP_SIZE 0x10000
+#define SRQ_DB_BAR_OFF 0x62000
+
+#define MAX_MR_SIZE 0x200000000000
+#define MAX_QP 0x3fff
+#define MAX_QP_WR 0x1000
+#define MAX_CQ 0x3fff
+#define MAX_CQE 0x200000
+#define MAX_MR 0xfffe
+#define MAX_MW 0xfffe
+#define MAX_PD 0xfffff
+#define MAX_SEND_SGE 0xf
+#define MAX_RECV_SGE 0xf
+#define MAX_SGE_RD 0xf
+#define MAX_QP_RD_ATOM 0x10
+#define MAX_RES_RD_ATOM 0x3fff0
+#define MAX_QP_INIT_RD_ATOM 0x10
+#define MAX_SRQ 0x200
+#define MAX_SRQ_WR 0x7fff
+#define MAX_SRQ_SGE 0xf
+#define LOCAL_CA_ACK_DELAY 16
+#define HCA_CORE_CLOCK (1000 * 1000UL)
+#define MAX_WQ_TYPE_RQ 0x3fff
+#define MAX_AH 0x10000
+#define MAX_FAST_REG_PAGE_LIST_LEN 0x200
+#define MAX_CQ_MODERATION_COUNT 0xffff
+#define MAX_CQ_MODERATION_PERIOD 0x1cc
+#define TIMESTAMP_MASK 0x1ffff
+#define MAX_MSG_SZ 0x100000
+
+enum zxdh_mmap_flag {
+	ZXDH_MMAP_IO_NC,
+	ZXDH_MMAP_IO_WC,
+	ZXDH_MMAP_PFN,
+	ZXDH_MMAP_HMC,
+	ZXDH_MMAP_IO_NC_BY_SIZE,
+};
+
+struct zxdh_ucontext {
+	struct ib_ucontext ibucontext;
+	struct zxdh_device *zdev;
+	struct rdma_user_mmap_entry *sq_db_mmap_entry;
+	struct rdma_user_mmap_entry *cq_db_mmap_entry;
+	struct rdma_user_mmap_entry *srq_db_mmap_entry;
+	struct list_head cq_reg_mem_list;
+	spinlock_t cq_reg_mem_list_lock; /* protect CQ memory list */
+	struct list_head qp_reg_mem_list;
+	spinlock_t qp_reg_mem_list_lock; /* protect QP memory list */
+	struct list_head srq_reg_mem_list;
+	spinlock_t srq_reg_mem_list_lock; /* protect SRQ memory list */
+	int abi_ver;
+	atomic_t tx_port_affinity;
+};
+
+struct zxdh_pd {
+	struct ib_pd ibpd;
+	struct zxdh_sc_pd sc_pd;
+};
+
+struct zxdh_user_mmap_entry {
+	struct rdma_user_mmap_entry rdma_entry;
+	u64 bar_offset;
+	u8 mmap_flag;
+};
+
+void zxdh_ib_dealloc_device(struct ib_device *ibdev);
+
+static inline struct zxdh_pd *to_zpd(struct ib_pd *ibpd)
+{
+	return container_of(ibpd, struct zxdh_pd, ibpd);
+}
+
+static inline struct zxdh_ucontext *to_ucontext(struct ib_ucontext *ibucontext)
+{
+	return container_of(ibucontext, struct zxdh_ucontext, ibucontext);
+}
+
+static inline struct zxdh_user_mmap_entry *
+to_zxdh_mmap_entry(struct rdma_user_mmap_entry *rdma_entry)
+{
+	return container_of(rdma_entry, struct zxdh_user_mmap_entry,
+			    rdma_entry);
+}
+
+#endif /* ZRDMA_VERBS_H */
-- 
2.43.5


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

* [PATCH rdma v9 5/7] RDMA/zrdma: Implement device and port query operations
  2026-11-03 12:56 [PATCH rdma v9 0/7] Add ZTE DingHai Ethernet Protocol Driver for RDMA Yanze Zhang
                   ` (3 preceding siblings ...)
  2026-11-03 12:56 ` [PATCH rdma v9 4/7] RDMA/zrdma: Add hardware resource initialization and verbs skeleton Yanze Zhang
@ 2026-11-03 12:56 ` Yanze Zhang
  2026-11-03 13:25   ` sashiko-bot
  2026-11-03 12:56 ` [PATCH rdma v9 6/7] RDMA/zrdma: Add device probe and remove logic Yanze Zhang
  2026-11-03 12:56 ` [PATCH rdma v9 7/7] RDMA/zrdma: Implement context, PD, and mmap operations Yanze Zhang
  6 siblings, 1 reply; 15+ messages in thread
From: Yanze Zhang @ 2026-11-03 12:56 UTC (permalink / raw)
  To: jgg, leon, julianbraha, huangjunxian6, yanjun.zhu
  Cc: Markus.Elfring, lkp, linux-kernel, linux-rdma, wei.quan,
	han.junyang, ran.ming, han.chengfei, zhang.yanze

Add implementation for querying device attributes, port attributes,
PKey, and link layer information. Also include firmware version string
retrieval.

The device attributes report the limits of the hardware, the vendor id
and the firmware version, which is taken from the driver info of the
network device. The port attributes report the state and the speed of
the port, which is taken from the network device on every query. The
immutable port information describes the RoCE encapsulation of the
port.

Signed-off-by: Yanze Zhang <zhang.yanze@zte.com.cn>
---
 drivers/infiniband/hw/zrdma/zrdma_verbs.c | 300 ++++++++++++++++++++++
 1 file changed, 300 insertions(+)

diff --git a/drivers/infiniband/hw/zrdma/zrdma_verbs.c b/drivers/infiniband/hw/zrdma/zrdma_verbs.c
index 84ee7be418139..b5322a8e129bb 100644
--- a/drivers/infiniband/hw/zrdma/zrdma_verbs.c
+++ b/drivers/infiniband/hw/zrdma/zrdma_verbs.c
@@ -7,11 +7,305 @@
 #include "zrdma_main.h"
 #include "zrdma_verbs.h"
 #include "zrdma_ctrl.h"
+#include <linux/ctype.h>
+#include <linux/etherdevice.h>
+#include <linux/rtnetlink.h>
+
+/* Fetch the driver info for @zdev->netdev, or for its first lower device
+ * when it is a bond. The lower device list is protected by rtnl_lock.
+ *
+ * The lock is taken unconditionally. rtnl_is_locked() only tells whether
+ * some task holds the lock, not whether the current one does, so it must
+ * not be used to decide that the lock can be skipped: skipping it would
+ * walk the lower device list without its protection.
+ *
+ * The lock is needed for two reasons: the kernel requires it for the
+ * traversal of the lower device list, and it keeps a slave from being
+ * unlinked or unregistered while it is used. A reference on the device
+ * would not be enough, because it does not keep the private data of the
+ * driver of the slave alive during the unregistration.
+ *
+ * The callers run in process context, so taking the lock there cannot
+ * sleep in atomic context. None of the callers holds the rtnl lock
+ * itself: query_device() is called from the uverbs and from the
+ * registration path, get_dev_fw_str() from the sysfs and from the
+ * netlink path. The rtnl mutex is not recursive, so taking it here
+ * cannot deadlock.
+ */
+static bool zxdh_get_drvinfo(struct zxdh_device *zdev,
+			     struct ethtool_drvinfo *info)
+{
+	struct net_device *slave = NULL, *dev;
+	struct list_head *iter;
+	bool ret = true;
+
+	memset(info, 0, sizeof(*info));
+
+	if (!zdev->netdev)
+		return false;
+
+	rtnl_lock();
+
+	/* Only the master of a bond has the slaves in its lower device
+	 * list. A slave carries the bonding flag as well, but it has no
+	 * lower devices of its own.
+	 */
+	if (netif_is_bond_master(zdev->netdev))
+		netdev_for_each_lower_dev(zdev->netdev, slave, iter)
+			break;
+
+	dev = slave ? slave : zdev->netdev;
+	if (dev->ethtool_ops && dev->ethtool_ops->get_drvinfo)
+		dev->ethtool_ops->get_drvinfo(dev, info);
+	else
+		ret = false;
+
+	rtnl_unlock();
+
+	return ret;
+}
+
+static void extract_version(const char *input, char *output, size_t size)
+{
+	const char *v_start, *p;
+	size_t len = 0;
+	int dots = 0;
+
+	if (!output || !size)
+		return;
+
+	*output = '\0';
+
+	if (!input)
+		return;
+
+	/* The version is preceded by the model, e.g. "E310-V25.30.103.01".
+	 * Skip the model, so that only the version itself is reported.
+	 */
+	v_start = input;
+	for (p = input; *p; p++) {
+		if (p[0] == '-' && p[1] == 'V' && isdigit((unsigned char)p[2])) {
+			v_start = p + 2;
+			break;
+		}
+	}
+
+	/* Cut the vendor suffix, if any, and keep at most four dot
+	 * separated fields, which is what the fw_ver layout can hold.
+	 */
+	for (p = v_start; *p && *p != ' '; p++) {
+		if (*p == '.' && ++dots == 4)
+			break;
+		if (len + 1 >= size)
+			break;
+		output[len++] = *p;
+	}
+
+	output[len] = '\0';
+}
+
+static int zxdh_query_device(struct ib_device *ibdev,
+			     struct ib_device_attr *props,
+			     struct ib_udata *udata)
+{
+	struct zxdh_device *zdev = to_zdev(ibdev);
+	struct pci_dev *pcidev = zdev->rf->pcidev;
+	unsigned int major, sub_major, minor, sub_minor;
+	struct ethtool_drvinfo info;
+	char extracted_version[32] = {};
+	int err;
+
+	/* The driver has no device specific data to exchange. The core
+	 * calls this without udata while the device is being registered,
+	 * so udata is only inspected when it is there.
+	 */
+	err = ib_no_udata_io(udata);
+	if (err)
+		return err;
+
+	memset(props, 0, sizeof(*props));
+
+	if (zxdh_get_drvinfo(zdev, &info)) {
+		extract_version(info.fw_version, extracted_version,
+				 sizeof(extracted_version));
+		if (sscanf(extracted_version, "%u.%u.%u.%u", &major,
+			   &sub_major, &minor, &sub_minor) != 4) {
+			major = 0;
+			sub_major = 0;
+			minor = 0;
+			sub_minor = 0;
+		}
+	} else {
+		major = 0;
+		sub_major = 0;
+		minor = 0;
+		sub_minor = 0;
+	}
+
+	addrconf_addr_eui48((u8 *)&props->sys_image_guid,
+			    zdev->netdev->dev_addr);
+	props->fw_ver = ((u64)(major & 0xffff) << 48 |
+			 (u64)(sub_major & 0xffff) << 32 |
+			 (u64)(minor & 0xffff) << 16 |
+			 (u64)(sub_minor & 0xffff));
+	/* Only the capabilities that the driver implements are reported.
+	 * The memory management extensions need the advise_mr operation,
+	 * the notification of the completion queue needs req_notify_cq and
+	 * the RNR NAK generation needs the queue pair data path.
+	 */
+	props->device_cap_flags =
+		IB_DEVICE_MEM_WINDOW | IB_DEVICE_SYS_IMAGE_GUID;
+	props->vendor_id = pcidev->vendor;
+	props->vendor_part_id = pcidev->device;
+	props->hw_ver = pcidev->revision;
+	props->page_size_cap = SZ_4K | SZ_2M | SZ_1G;
+	props->max_mr_size = MAX_MR_SIZE;
+	props->max_qp = MAX_QP;
+	props->max_qp_wr = MAX_QP_WR;
+	props->max_cq = MAX_CQ;
+	props->max_cqe = MAX_CQE;
+	props->max_mr = MAX_MR;
+	props->max_mw = MAX_MW;
+	props->max_pd = MAX_PD;
+	props->max_send_sge = MAX_SEND_SGE;
+	props->max_recv_sge = MAX_RECV_SGE;
+	props->max_sge_rd = MAX_SGE_RD;
+	props->max_qp_rd_atom = MAX_QP_RD_ATOM;
+	props->max_res_rd_atom = MAX_RES_RD_ATOM;
+	props->max_qp_init_rd_atom = MAX_QP_INIT_RD_ATOM;
+	props->max_srq = MAX_SRQ;
+	props->max_srq_wr = MAX_SRQ_WR;
+	props->max_srq_sge = MAX_SRQ_SGE;
+	props->local_ca_ack_delay = LOCAL_CA_ACK_DELAY;
+	props->hca_core_clock = HCA_CORE_CLOCK;
+	props->max_wq_type_rq = MAX_WQ_TYPE_RQ;
+	if (rdma_protocol_roce(ibdev, rdma_start_port(ibdev))) {
+		props->max_pkeys = ZXDH_PKEY_TBL_SZ;
+		props->max_ah = MAX_AH;
+		props->max_mcast_grp = 0;
+		props->max_mcast_qp_attach = 0;
+		props->max_total_mcast_qp_attach = 0;
+	}
+	props->max_fast_reg_page_list_len = MAX_FAST_REG_PAGE_LIST_LEN;
+	props->cq_caps.max_cq_moderation_count = MAX_CQ_MODERATION_COUNT;
+	props->cq_caps.max_cq_moderation_period = MAX_CQ_MODERATION_PERIOD;
+	props->timestamp_mask = TIMESTAMP_MASK;
+
+	return 0;
+}
+
+static int zxdh_query_port(struct ib_device *ibdev, u32 port,
+			   struct ib_port_attr *props)
+{
+	struct zxdh_device *zdev = to_zdev(ibdev);
+	struct net_device *netdev = zdev->netdev;
+
+	props->max_mtu = IB_MTU_4096;
+	props->active_mtu = ib_mtu_int_to_enum(netdev->mtu - ZXDH_MTU_HEADER_RSV);
+	props->lid = 0;
+	props->lmc = 0;
+	props->sm_lid = 0;
+	props->sm_sl = 0;
+	if (netif_carrier_ok(netdev) && netif_running(netdev)) {
+		props->state = IB_PORT_ACTIVE;
+		props->phys_state = IB_PORT_PHYS_STATE_LINK_UP;
+	} else {
+		props->state = IB_PORT_DOWN;
+		props->phys_state = IB_PORT_PHYS_STATE_DISABLED;
+	}
+
+	/* The link speed is read from the netdev on every query, so a
+	 * link change is never reported with a stale value.
+	 */
+	if (ib_get_eth_speed(ibdev, port, &props->active_speed,
+			     &props->active_width))
+		pr_warn_ratelimited("zrdma: failed to get the port speed\n");
+
+	if (rdma_protocol_roce(ibdev, port)) {
+		props->gid_tbl_len = ZXDH_GID_TBL_LEN;
+		props->ip_gids = true;
+		props->pkey_tbl_len = ZXDH_PKEY_TBL_SZ;
+	} else {
+		props->gid_tbl_len = 1;
+	}
+	props->max_msg_sz = MAX_MSG_SZ;
+	props->qkey_viol_cntr = 0;
+
+	return 0;
+}
+
+static enum rdma_link_layer zxdh_get_link_layer(struct ib_device *ibdev,
+						u32 port_num)
+{
+	return IB_LINK_LAYER_ETHERNET;
+}
+
+static int zxdh_query_pkey(struct ib_device *ibdev, u32 port, u16 index,
+			   u16 *pkey)
+{
+	if (index >= ZXDH_PKEY_TBL_SZ)
+		return -EINVAL;
+
+	*pkey = ZXDH_DEFAULT_PKEY;
+	return 0;
+}
+
+static int zxdh_roce_port_immutable(struct ib_device *ibdev, u32 port_num,
+				    struct ib_port_immutable *immutable)
+{
+	/* The core passes a pointer to port_data[port_num].immutable, so
+	 * the values are visible to rdma_protocol_roce() as soon as they
+	 * are written here. They are filled in directly instead of asking
+	 * zxdh_query_port(), because that helper is only meant for a
+	 * device that is already registered.
+	 */
+	/* The management datagrams are not supported, so the MAD and the
+	 * CM capability are not reported and the size of the management
+	 * datagram is zero.
+	 */
+	immutable->core_cap_flags = RDMA_CORE_CAP_PROT_ROCE_UDP_ENCAP |
+				    RDMA_CORE_CAP_PROT_ROCE;
+	immutable->max_mad_size = 0;
+	immutable->pkey_tbl_len = ZXDH_PKEY_TBL_SZ;
+	immutable->gid_tbl_len = ZXDH_GID_TBL_LEN;
+
+	return 0;
+}
+
+static void zxdh_get_dev_fw_str(struct ib_device *dev, char *str)
+{
+	struct zxdh_device *zdev = to_zdev(dev);
+	struct ethtool_drvinfo info;
+	char extracted_version[32];
+
+	strscpy(str, "N/A", IB_FW_VERSION_NAME_MAX);
+
+	if (!zxdh_get_drvinfo(zdev, &info))
+		return;
+
+	extract_version(info.fw_version, extracted_version,
+				 sizeof(extracted_version));
+	/* Keep the placeholder when no version could be extracted. */
+	if (extracted_version[0])
+		strscpy(str, extracted_version, IB_FW_VERSION_NAME_MAX);
+}
+
+static void zxdh_init_roce_device(struct zxdh_device *zdev)
+{
+	zdev->ibdev.node_type = RDMA_NODE_IB_CA;
+	addrconf_addr_eui48((u8 *)&zdev->ibdev.node_guid,
+			    zdev->netdev->dev_addr);
+}
 
 static int zxdh_init_rdma_device(struct zxdh_device *zdev)
 {
 	struct pci_dev *pcidev = zdev->rf->pcidev;
 
+	if (zdev->roce_mode)
+		zxdh_init_roce_device(zdev);
+	else
+		return -EPFNOSUPPORT;
+
 	zdev->ibdev.phys_port_cnt = 1;
 	/* The core divides by num_comp_vectors in ib_cq_pool_get() and
 	 * rejects every uverbs CQ creation when it is zero, so the count
@@ -47,4 +341,10 @@ const struct ib_device_ops zxdh_dev_ops = {
 	.owner = THIS_MODULE,
 	.driver_id = RDMA_DRIVER_ZRDMA,
 	.uverbs_abi_ver = ZXDH_ABI_VER,
+	.query_device = zxdh_query_device,
+	.query_port = zxdh_query_port,
+	.query_pkey = zxdh_query_pkey,
+	.get_link_layer = zxdh_get_link_layer,
+	.get_port_immutable = zxdh_roce_port_immutable,
+	.get_dev_fw_str = zxdh_get_dev_fw_str,
 };
-- 
2.43.5


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

* [PATCH rdma v9 6/7] RDMA/zrdma: Add device probe and remove logic
  2026-11-03 12:56 [PATCH rdma v9 0/7] Add ZTE DingHai Ethernet Protocol Driver for RDMA Yanze Zhang
                   ` (4 preceding siblings ...)
  2026-11-03 12:56 ` [PATCH rdma v9 5/7] RDMA/zrdma: Implement device and port query operations Yanze Zhang
@ 2026-11-03 12:56 ` Yanze Zhang
  2026-11-03 13:17   ` sashiko-bot
  2026-11-03 12:56 ` [PATCH rdma v9 7/7] RDMA/zrdma: Implement context, PD, and mmap operations Yanze Zhang
  6 siblings, 1 reply; 15+ messages in thread
From: Yanze Zhang @ 2026-11-03 12:56 UTC (permalink / raw)
  To: jgg, leon, julianbraha, huangjunxian6, yanjun.zhu
  Cc: Markus.Elfring, lkp, linux-kernel, linux-rdma, wei.quan,
	han.junyang, ran.ming, han.chengfei, zhang.yanze

Implement the auxiliary bus probe and remove functions, including device
initialization, hardware resource setup, and IB device registration.
This replaces the stub probe from the initial skeleton patch. The file
is modified rather than deleted, so every commit of the series builds on
its own.

The device ops are installed right after ib_alloc_device(), so that the
dealloc_driver hook is in place before any resource is taken. The hook
releases the hardware resources and the address handle list lock, and it
only destroys the lock when it was actually initialised. The pci device
is owned by the PF driver, so the driver does not release it.

The netdev is bound to the IB device and the DMA capable device is
handed to the core before the device is registered, so that the port
queries read the netdev the auxiliary device belongs to and the core
does not have to fall back to the kernel virtual address of the
scatterlists.

Signed-off-by: Yanze Zhang <zhang.yanze@zte.com.cn>
---
 drivers/infiniband/hw/zrdma/zrdma_main.c  | 172 +++++++++++++++++++++-
 drivers/infiniband/hw/zrdma/zrdma_verbs.c |  56 +++++++
 2 files changed, 225 insertions(+), 3 deletions(-)

diff --git a/drivers/infiniband/hw/zrdma/zrdma_main.c b/drivers/infiniband/hw/zrdma/zrdma_main.c
index 80856c7ff6b2a..c320513c13879 100644
--- a/drivers/infiniband/hw/zrdma/zrdma_main.c
+++ b/drivers/infiniband/hw/zrdma/zrdma_main.c
@@ -6,11 +6,96 @@
 
 #include <linux/module.h>
 #include <linux/auxiliary_bus.h>
+#include <linux/types.h>
+#include <linux/netdevice.h>
+#include <rdma/ib_verbs.h>
+
+#include "zrdma_main.h"
+#include "zrdma_verbs.h"
 
 MODULE_LICENSE("Dual BSD/GPL");
 MODULE_AUTHOR("Yanze Zhang <zhang.yanze@zte.com.cn>");
 MODULE_DESCRIPTION("ZTE Ethernet Protocol Driver for RDMA");
 
+/* Must be called after zxdh_get_common_func_num_max(). */
+/* The firmware supports the interrupt request and the interrupt free
+ * opcodes when the highest opcode it reports is beyond the free one.
+ */
+static void zxdh_get_net_irq_cap(struct zxdh_pci_f *rf)
+{
+	if (rf->common_func_num_max > ZXDH_FUNC_IRQ_FREE &&
+	    rf->common_func_num_max != 0xFF)
+		rf->net_irq_cap = true;
+}
+
+static void zxdh_get_common_func_num_max(struct zxdh_pci_f *rf)
+{
+	int num_max;
+
+	if (rf->gen_ops.zxdh_common_func) {
+		num_max = rf->gen_ops.zxdh_common_func(NULL, NULL,
+						       ZXDH_FUNC_NUM_REQUIRE);
+		if (num_max >= 0 && num_max != 0xFF) {
+			rf->common_func_num_max = num_max;
+			return;
+		}
+	}
+	rf->common_func_num_max = -1;
+}
+
+static void zxdh_fill_device_info(struct zxdh_device *zdev,
+				  struct zxdh_rdma_core_dev *zdev_info)
+{
+	struct zxdh_pci_f *rf = zdev->rf;
+
+	rf->ftype = ZXDH_FUNC_TYPE(zdev_info->vport_id);
+	rf->pf_id = ZXDH_PF_ID(zdev_info->vport_id);
+	rf->sc_dev.ep_id = ZXDH_EP_ID(zdev_info->vport_id);
+	rf->ep_id = rf->sc_dev.ep_id;
+	rf->sc_dev.driver_load = true;
+
+	rf->zdev_info = zdev_info;
+	rf->pcidev = zdev_info->pdev;
+
+	rf->msix_count = zdev_info->msix_count;
+	rf->msix_entries = zdev_info->msix_entries;
+	if (rf->msix_count)
+		rf->sc_dev.max_ceqs = (rf->msix_count - 1);
+	else
+		rf->sc_dev.max_ceqs = 0;
+	/* The number of completion vectors is reported to the core as
+	 * ib_device.num_comp_vectors. The core divides by it and
+	 * rejects every uverbs CQ creation when it is zero, so the count
+	 * is never allowed to drop below one.
+	 */
+	rf->ceqs_count = rf->sc_dev.max_ceqs ? rf->sc_dev.max_ceqs : 1;
+	rf->rdma_ver = ZXDH_GEN_2;
+	rf->rst_to = ZXDH_RST_TIMEOUT_HZ;
+	rf->qp_index = 0;
+	rf->gen_ops.zxdh_common_func = NULL;
+	rf->net_irq_cap = false;
+	rf->dh_dev = NULL;
+	if (FIELD_GET(ZXDH_RDMA_COMM_FUNC, zdev_info->ver.support) ==
+	    ZXDH_RDMA_COMMON_FUNC_CAP) {
+		if (zdev_info->ops && zdev_info->ops->zxdh_common_func)
+			rf->gen_ops.zxdh_common_func =
+				zdev_info->ops->zxdh_common_func;
+	}
+
+	zxdh_get_common_func_num_max(rf);
+	zxdh_get_net_irq_cap(rf);
+
+	rf->zdev = zdev;
+
+	atomic_set(&zdev->tx_port_affinity, 0);
+	atomic_set(&zdev->sport_counter, 0);
+
+	INIT_LIST_HEAD(&zdev->ah_list);
+	mutex_init(&zdev->ah_list_lock);
+	zdev->init_state = INITIAL_STATE;
+	zdev->roce_mode = true;
+}
+
 /* The name has to match the auxiliary device that the DingHai PF
  * driver creates.
  */
@@ -26,14 +111,95 @@ MODULE_DEVICE_TABLE(auxiliary, zxdh_auxiliary_id_table);
 static int zxdh_probe(struct auxiliary_device *aux_dev,
 		      const struct auxiliary_device_id *id)
 {
-	/* Placeholder: Real probe logic will be added in subsequent patches */
-	dev_info(&aux_dev->dev, "ZTE DingHai RDMA device detected (stub)\n");
+	struct zxdh_auxiliary_dev *zxdh_adev =
+		container_of(aux_dev, struct zxdh_auxiliary_dev, adev);
+	struct zxdh_device *zdev;
+	struct zxdh_pci_f *rf;
+	struct net_device *netdev;
+	int err;
+
+	if (!zxdh_adev->rdma_ops || !zxdh_adev->rdma_ops->get_rdma_netdev) {
+		pr_err("zrdma: rdma_ops or get_rdma_netdev is NULL\n");
+		return -EINVAL;
+	}
+
+	if (!zxdh_adev->zxdh_info) {
+		pr_err("zrdma: zxdh_info is NULL\n");
+		return -EINVAL;
+	}
+
+	/* The pci device is the DMA capable device of the IB device and
+	 * the source of the vendor id, so it has to be there.
+	 */
+	if (!zxdh_adev->zxdh_info->pdev) {
+		pr_err("zrdma: pci device is NULL\n");
+		return -EINVAL;
+	}
+
+	netdev = zxdh_adev->rdma_ops->get_rdma_netdev(zxdh_adev->parent);
+	if (!netdev) {
+		pr_err("zrdma: failed to get netdev\n");
+		return -ENODEV;
+	}
+
+	zdev = ib_alloc_device(zxdh_device, ibdev);
+	if (!zdev)
+		return -ENOMEM;
+
+	/* Install the device ops before anything can fail, so that every
+	 * ib_dealloc_device() below runs the dealloc_driver hook and the
+	 * resources allocated so far are released.
+	 */
+	ib_set_device_ops(&zdev->ibdev, &zxdh_dev_ops);
+
+	zdev->zxdh_adev = zxdh_adev;
+	zdev->netdev = netdev;
+
+	zdev->rf = kzalloc_obj(*zdev->rf);
+	if (!zdev->rf) {
+		ib_dealloc_device(&zdev->ibdev);
+		return -ENOMEM;
+	}
+
+	zxdh_fill_device_info(zdev, zxdh_adev->zxdh_info);
+
+	rf = zdev->rf;
+	err = zxdh_ctrl_init_hw(rf);
+	if (err)
+		goto err_dealloc;
+
+	err = zxdh_ib_register_device(zdev);
+	if (err)
+		goto err_dealloc;
+
+	dev_set_drvdata(&aux_dev->dev, zdev);
+
 	return 0;
+
+err_dealloc:
+	ib_dealloc_device(&zdev->ibdev);
+
+	return err;
 }
 
 static void zxdh_remove(struct auxiliary_device *aux_dev)
 {
-	dev_info(&aux_dev->dev, "ZTE DingHai RDMA device removed (stub)\n");
+	struct zxdh_device *zdev = dev_get_drvdata(&aux_dev->dev);
+
+	if (!zdev) {
+		dev_err(&aux_dev->dev, "%s: zdev is NULL\n", __func__);
+		return;
+	}
+
+	/* Clear the drvdata before the device is freed, so that it does
+	 * not point to the released ib_device any more.
+	 */
+	dev_set_drvdata(&aux_dev->dev, NULL);
+
+	/* No 'get' on the ib_device, so the _and_put variant would
+	 * underflow ib_device.refcount; see cover letter.
+	 */
+	ib_unregister_device(&zdev->ibdev);
 }
 
 static struct auxiliary_driver zxdh_auxiliary_drv = {
diff --git a/drivers/infiniband/hw/zrdma/zrdma_verbs.c b/drivers/infiniband/hw/zrdma/zrdma_verbs.c
index b5322a8e129bb..a410ef4521ad5 100644
--- a/drivers/infiniband/hw/zrdma/zrdma_verbs.c
+++ b/drivers/infiniband/hw/zrdma/zrdma_verbs.c
@@ -11,6 +11,31 @@
 #include <linux/etherdevice.h>
 #include <linux/rtnetlink.h>
 
+/* Release everything the probe path may have allocated. The hook is
+ * called from ib_dealloc_device(), so it must tolerate a partially
+ * initialised device.
+ */
+void zxdh_ib_dealloc_device(struct ib_device *ibdev)
+{
+	struct zxdh_device *zdev = to_zdev(ibdev);
+
+	if (!zdev)
+		return;
+
+	if (zdev->rf) {
+		kvfree(zdev->rf->qp_cnt_8k_idxs);
+		kvfree(zdev->rf->mem_rsrc);
+		kfree(zdev->rf);
+		zdev->rf = NULL;
+	}
+
+	/* ah_list_lock is only initialised by zxdh_fill_device_info(),
+	 * which is skipped when the probe fails earlier.
+	 */
+	if (zdev->init_state != INVALID_STATE)
+		mutex_destroy(&zdev->ah_list_lock);
+}
+
 /* Fetch the driver info for @zdev->netdev, or for its first lower device
  * when it is a bond. The lower device list is protected by rtnl_lock.
  *
@@ -317,6 +342,17 @@ static int zxdh_init_rdma_device(struct zxdh_device *zdev)
 	return 0;
 }
 
+static void zxdh_port_ibevent(struct zxdh_device *zdev)
+{
+	struct ib_event event;
+
+	event.device = &zdev->ibdev;
+	event.element.port_num = 1;
+	event.event = zdev->ibdev_status ? IB_EVENT_PORT_ACTIVE :
+						 IB_EVENT_PORT_ERR;
+	ib_dispatch_event(&event);
+}
+
 int zxdh_ib_register_device(struct zxdh_device *zdev)
 {
 	int ret;
@@ -325,13 +361,32 @@ int zxdh_ib_register_device(struct zxdh_device *zdev)
 	if (ret)
 		return ret;
 
+	ret = ib_device_set_netdev(&zdev->ibdev, zdev->netdev, 1);
+	if (ret)
+		goto error;
+
+	zdev->rf->hw.device = &zdev->rf->pcidev->dev;
+	dma_set_max_seg_size(zdev->rf->hw.device, SZ_1G);
+
+	/* Publish the link state before the device becomes visible to
+	 * userspace, so a racing ULP never observes a stale status.
+	 */
+	zdev->ibdev_status = 1;
+
 	ret = ib_register_device(&zdev->ibdev, "zrdma%d", zdev->rf->hw.device);
 	if (ret)
 		goto error;
 
+	zxdh_port_ibevent(zdev);
+
 	return 0;
 
 error:
+	/* There is nothing to undo here: ib_device_set_netdev() only fails
+	 * before it takes the netdev reference, and the reference it takes
+	 * on success is released by free_netdevs() when the device is
+	 * deallocated.
+	 */
 	pr_err("zrdma: Register RDMA device fail, ret=%d\n", ret);
 
 	return ret;
@@ -341,6 +396,7 @@ const struct ib_device_ops zxdh_dev_ops = {
 	.owner = THIS_MODULE,
 	.driver_id = RDMA_DRIVER_ZRDMA,
 	.uverbs_abi_ver = ZXDH_ABI_VER,
+	.dealloc_driver = zxdh_ib_dealloc_device,
 	.query_device = zxdh_query_device,
 	.query_port = zxdh_query_port,
 	.query_pkey = zxdh_query_pkey,
-- 
2.43.5


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

* [PATCH rdma v9 7/7] RDMA/zrdma: Implement context, PD, and mmap operations
  2026-11-03 12:56 [PATCH rdma v9 0/7] Add ZTE DingHai Ethernet Protocol Driver for RDMA Yanze Zhang
                   ` (5 preceding siblings ...)
  2026-11-03 12:56 ` [PATCH rdma v9 6/7] RDMA/zrdma: Add device probe and remove logic Yanze Zhang
@ 2026-11-03 12:56 ` Yanze Zhang
  2026-11-03 13:23   ` sashiko-bot
  6 siblings, 1 reply; 15+ messages in thread
From: Yanze Zhang @ 2026-11-03 12:56 UTC (permalink / raw)
  To: jgg, leon, julianbraha, huangjunxian6, yanjun.zhu
  Cc: Markus.Elfring, lkp, linux-kernel, linux-rdma, wei.quan,
	han.junyang, ran.ming, han.chengfei, zhang.yanze

Add implementation for allocation/deallocation of Protection Domains (PD),
User Contexts, and memory mapping (mmap) for doorbells.

The SRQ doorbell area is not page aligned on 16K and 64K page systems, so
the mapping length is extended to the page boundary and the size
reported to userspace is the very same length. The V1 and V2 contexts do
not know the size of the SRQ doorbell area, so only the first page is
mapped for them.

Signed-off-by: Yanze Zhang <zhang.yanze@zte.com.cn>
---
 drivers/infiniband/hw/zrdma/zrdma_verbs.c | 351 ++++++++++++++++++++++
 1 file changed, 351 insertions(+)

diff --git a/drivers/infiniband/hw/zrdma/zrdma_verbs.c b/drivers/infiniband/hw/zrdma/zrdma_verbs.c
index a410ef4521ad5..fb33bf1bde615 100644
--- a/drivers/infiniband/hw/zrdma/zrdma_verbs.c
+++ b/drivers/infiniband/hw/zrdma/zrdma_verbs.c
@@ -10,6 +10,7 @@
 #include <linux/ctype.h>
 #include <linux/etherdevice.h>
 #include <linux/rtnetlink.h>
+#include <rdma/ib_user_verbs.h>
 
 /* Release everything the probe path may have allocated. The hook is
  * called from ib_dealloc_device(), so it must tolerate a partially
@@ -392,15 +393,365 @@ int zxdh_ib_register_device(struct zxdh_device *zdev)
 	return ret;
 }
 
+static void zxdh_sc_pd_init(struct zxdh_sc_dev *dev, struct zxdh_sc_pd *pd,
+			    u32 pd_id, int abi_ver)
+{
+	pd->pd_id = pd_id;
+	pd->abi_ver = abi_ver;
+	pd->dev = dev;
+}
+
+static int zxdh_alloc_pd(struct ib_pd *pd, struct ib_udata *udata)
+{
+	struct zxdh_device *zdev = to_zdev(pd->device);
+	struct zxdh_sc_dev *dev = &zdev->rf->sc_dev;
+	struct zxdh_alloc_pd_resp uresp = {};
+	struct zxdh_pd *zpd = to_zpd(pd);
+	struct zxdh_pci_f *rf = zdev->rf;
+	struct zxdh_sc_pd *sc_pd;
+	u32 pd_id;
+	int err;
+
+	/* The user has to provide a buffer for the whole response. A short
+	 * buffer is reported instead of being silently truncated, and no
+	 * resource is taken for it.
+	 */
+	if (udata && udata->outlen < sizeof(uresp))
+		return -ENOSPC;
+
+	/* The command takes no input from the user space. */
+	if (udata) {
+		err = ib_is_udata_in_empty(udata);
+		if (err)
+			return err;
+	}
+
+	err = zxdh_alloc_rsrc(rf, rf->allocated_pds, rf->max_pd, &pd_id,
+			      &rf->next_pd, "PD");
+	if (err) {
+		pr_warn_ratelimited("zrdma: PD allocation failed err=%d\n",
+				    err);
+		return err;
+	}
+
+	sc_pd = &zpd->sc_pd;
+	if (udata) {
+		struct zxdh_ucontext *ucontext;
+
+		ucontext = rdma_udata_to_drv_context(udata,
+						     struct zxdh_ucontext,
+						     ibucontext);
+
+		zxdh_sc_pd_init(dev, sc_pd, pd_id, ucontext->abi_ver);
+		uresp.pd_id = pd_id;
+		if (ib_respond_udata(udata, uresp)) {
+			err = -EFAULT;
+			goto error;
+		}
+	} else {
+		/* A protection domain that the kernel allocates has no user
+		 * context, it uses the default ABI version.
+		 */
+		zxdh_sc_pd_init(dev, sc_pd, pd_id, ZXDH_ABI_VER);
+	}
+
+	return 0;
+
+error:
+	zxdh_free_rsrc(rf, rf->allocated_pds, pd_id);
+
+	return err;
+}
+
+static struct rdma_user_mmap_entry *
+zxdh_mmap_entry_insert(struct zxdh_ucontext *ucontext, u64 bar_offset,
+		       size_t length, enum zxdh_mmap_flag mmap_flag,
+		       u64 *mmap_offset)
+{
+	struct zxdh_user_mmap_entry *entry =
+		kzalloc(sizeof(*entry), GFP_KERNEL);
+	int ret;
+
+	if (!entry)
+		return NULL;
+
+	entry->bar_offset = bar_offset;
+	entry->mmap_flag = mmap_flag;
+
+	ret = rdma_user_mmap_entry_insert(&ucontext->ibucontext,
+					  &entry->rdma_entry, length);
+	if (ret) {
+		kfree(entry);
+		return NULL;
+	}
+	*mmap_offset = rdma_user_mmap_get_offset(&entry->rdma_entry);
+
+	return &entry->rdma_entry;
+}
+
+/* The SRQ doorbell area starts at SRQ_DB_BAR_OFF, which is not page
+ * aligned once the page size is 16K or 64K. The mapping therefore has to
+ * start at the page holding the doorbell and has to be large enough to
+ * cover the whole doorbell area.
+ */
+static u64 zxdh_get_srq_db_mmap_size(void)
+{
+	return round_up((SRQ_DB_BAR_OFF & ZXDH_PAGE_OFFSET_NUM) +
+			SRQ_DB_MMAP_SIZE, PAGE_SIZE);
+}
+
+static int zxdh_alloc_ucontext(struct ib_ucontext *uctx, struct ib_udata *udata)
+{
+	struct zxdh_ucontext *ucontext = to_ucontext(uctx);
+	struct zxdh_alloc_ucontext_resp uresp = {};
+	struct ib_device *ibdev = uctx->device;
+	struct zxdh_device *zdev = to_zdev(ibdev);
+	struct zxdh_alloc_ucontext_req req = {};
+	u64 srq_db_mmap_size;
+	int err;
+
+	/* The request is validated against the size of the structure, so
+	 * that a truncated or an oversized buffer is rejected instead of
+	 * being read partially.
+	 */
+	err = ib_copy_validate_udata_in(udata, req, rsvd8);
+	if (err)
+		return err;
+
+	if (req.userspace_ver != ZXDH_CONTEXT_VER_V1 &&
+	    req.userspace_ver != ZXDH_CONTEXT_VER_V2 &&
+	    req.userspace_ver != ZXDH_CONTEXT_VER_V3) {
+		pr_err_ratelimited("zrdma: Invalid userspace_ver%d\n",
+				   req.userspace_ver);
+		return -EINVAL;
+	}
+
+	/* The response carries the keys of the doorbell mappings, so the
+	 * user has to provide a buffer for the whole of it. A short buffer
+	 * is reported instead of being silently truncated.
+	 */
+	if (udata->outlen < sizeof(uresp))
+		return -ENOSPC;
+
+	ucontext->zdev = zdev;
+	ucontext->abi_ver = req.userspace_ver;
+
+	uresp.srq_db_bar_off = SRQ_DB_BAR_OFF & ZXDH_PAGE_OFFSET_NUM;
+
+	ucontext->sq_db_mmap_entry =
+		zxdh_mmap_entry_insert(ucontext, SQ_DB_BAR_OFF, PAGE_SIZE,
+				       ZXDH_MMAP_IO_NC,
+				       &uresp.sq_db_mmap_key);
+	if (!ucontext->sq_db_mmap_entry)
+		return -ENOMEM;
+
+	ucontext->cq_db_mmap_entry =
+		zxdh_mmap_entry_insert(ucontext, CQ_DB_BAR_OFF, PAGE_SIZE,
+				       ZXDH_MMAP_IO_NC,
+				       &uresp.cq_db_mmap_key);
+	if (!ucontext->cq_db_mmap_entry) {
+		rdma_user_mmap_entry_remove(ucontext->sq_db_mmap_entry);
+		ucontext->sq_db_mmap_entry = NULL;
+		return -ENOMEM;
+	}
+
+	/* The mapping length and the size reported to userspace have to
+	 * match, otherwise rdma_user_mmap_entry_get() rejects the mmap.
+	 *
+	 * The V1 and V2 contexts do not know the size of the SRQ doorbell
+	 * area, so only the first page is mapped for them. The V3 context
+	 * gets the size of the whole area in the response.
+	 */
+	if (ucontext->abi_ver == ZXDH_CONTEXT_VER_V1 ||
+	    ucontext->abi_ver == ZXDH_CONTEXT_VER_V2)
+		srq_db_mmap_size = PAGE_SIZE;
+	else
+		srq_db_mmap_size = zxdh_get_srq_db_mmap_size();
+
+	ucontext->srq_db_mmap_entry =
+		zxdh_mmap_entry_insert(ucontext, SRQ_DB_BAR_OFF,
+				       srq_db_mmap_size,
+				       ZXDH_MMAP_IO_NC_BY_SIZE,
+				       &uresp.srq_db_mmap_key);
+	if (!ucontext->srq_db_mmap_entry) {
+		rdma_user_mmap_entry_remove(ucontext->sq_db_mmap_entry);
+		ucontext->sq_db_mmap_entry = NULL;
+		rdma_user_mmap_entry_remove(ucontext->cq_db_mmap_entry);
+		ucontext->cq_db_mmap_entry = NULL;
+		pr_err("zrdma: srq_db_mmap_entry is NULL!\n");
+		return -ENOMEM;
+	}
+
+	uresp.srq_db_mmap_size = srq_db_mmap_size;
+	uresp.kernel_ver = ZXDH_CONTEXT_VER_V3;
+	uresp.hw_rev = ZXDH_GEN_2;
+	uresp.chip_rev = CHIP_VERSION;
+	uresp.rdma_tool_flags =
+		ZXDH_QP_EXTEND_OP | ZXDH_CAPTURE | ZXDH_GET_HW_DATA |
+		ZXDH_GET_HW_OBJECT_DATA | ZXDH_CHECK_HW_HEALTH |
+		ZXDH_RDMA_TOOL_CFG_DEV_PARAM | ZXDH_RDMA_TOOL_READ_RAM |
+		ZXDH_RDMA_TOOL_DEVX_MODIFY_CQ | ZXDH_RDMA_SET_CREDIT_CAP |
+		ZXDH_RDMA_SWITCH | ZXDH_RDMA_TOOL_DEVX_EXT_MEM |
+		ZXDH_RDMA_TOOL_PRIV_EXT |
+		ZXDH_RDMA_TOOL_IOVA_CAP;
+
+	uresp.feature_flags = ZXDH_FEATURE_RTS_AE | ZXDH_FEATURE_CQ_RESIZE |
+			      ZXDH_FEATURE_64_BYTE_CQE;
+	uresp.max_hw_wq_frags = MAX_HW_WQ_FRAGS;
+	uresp.max_hw_read_sges = MAX_HW_READ_SGES;
+	uresp.max_hw_inline = MAX_HW_INLINE;
+	uresp.max_hw_srq_wr = MAX_HW_SRQ_WR;
+	uresp.max_hw_rq_quanta = MAX_HW_RQ_QUANTA;
+	uresp.max_hw_srq_quanta = MAX_HW_SRQ_QUANTA;
+	uresp.max_hw_wq_quanta = MAX_HW_WQ_QUANTA;
+	uresp.max_hw_sq_chunk = MAX_HW_SQ_CHUNK;
+	uresp.max_hw_cq_size = MAX_HW_CQ_SIZE;
+	uresp.min_hw_cq_size = MIN_HW_CQ_SIZE;
+	uresp.db_addr_type = ZXDH_DB_ADDR_BAR;
+	uresp.sq_db_bar_off = SQ_DB_BAR_OFF & ZXDH_PAGE_OFFSET_NUM;
+	uresp.cq_db_bar_off = CQ_DB_BAR_OFF & ZXDH_PAGE_OFFSET_NUM;
+
+	if (ib_respond_udata(udata, uresp)) {
+		rdma_user_mmap_entry_remove(ucontext->sq_db_mmap_entry);
+		ucontext->sq_db_mmap_entry = NULL;
+		rdma_user_mmap_entry_remove(ucontext->cq_db_mmap_entry);
+		ucontext->cq_db_mmap_entry = NULL;
+		rdma_user_mmap_entry_remove(ucontext->srq_db_mmap_entry);
+		ucontext->srq_db_mmap_entry = NULL;
+		return -EFAULT;
+	}
+
+	atomic_set(&ucontext->tx_port_affinity,
+		   atomic_add_return(1, &zdev->tx_port_affinity));
+
+	INIT_LIST_HEAD(&ucontext->cq_reg_mem_list);
+	spin_lock_init(&ucontext->cq_reg_mem_list_lock);
+	INIT_LIST_HEAD(&ucontext->qp_reg_mem_list);
+	spin_lock_init(&ucontext->qp_reg_mem_list_lock);
+	INIT_LIST_HEAD(&ucontext->srq_reg_mem_list);
+	spin_lock_init(&ucontext->srq_reg_mem_list_lock);
+
+	return 0;
+}
+
+static int zxdh_dealloc_pd(struct ib_pd *ibpd, struct ib_udata *udata)
+{
+	struct zxdh_pd *zpd = to_zpd(ibpd);
+	struct zxdh_device *zdev = to_zdev(ibpd->device);
+	int err;
+
+	/* The command takes no input from the user space and returns no
+	 * response data.
+	 */
+	err = ib_no_udata_io(udata);
+	if (err)
+		return err;
+
+	zxdh_free_rsrc(zdev->rf, zdev->rf->allocated_pds, zpd->sc_pd.pd_id);
+	return 0;
+}
+
+static void zxdh_dealloc_ucontext(struct ib_ucontext *context)
+{
+	struct zxdh_ucontext *ucontext = to_ucontext(context);
+
+	if (!ucontext)
+		return;
+
+	if (ucontext->sq_db_mmap_entry) {
+		rdma_user_mmap_entry_remove(ucontext->sq_db_mmap_entry);
+		ucontext->sq_db_mmap_entry = NULL;
+	}
+	if (ucontext->cq_db_mmap_entry) {
+		rdma_user_mmap_entry_remove(ucontext->cq_db_mmap_entry);
+		ucontext->cq_db_mmap_entry = NULL;
+	}
+	if (ucontext->srq_db_mmap_entry) {
+		rdma_user_mmap_entry_remove(ucontext->srq_db_mmap_entry);
+		ucontext->srq_db_mmap_entry = NULL;
+	}
+}
+
+static void zxdh_mmap_free(struct rdma_user_mmap_entry *entry)
+{
+	struct zxdh_user_mmap_entry *zentry = to_zxdh_mmap_entry(entry);
+
+	kfree(zentry);
+}
+
+static int zxdh_mmap(struct ib_ucontext *context, struct vm_area_struct *vma)
+{
+	struct rdma_user_mmap_entry *rdma_entry;
+	struct zxdh_user_mmap_entry *entry;
+	struct zxdh_ucontext *ucontext;
+	u64 pfn;
+	int ret;
+
+	ucontext = to_ucontext(context);
+
+	rdma_entry = rdma_user_mmap_entry_get(&ucontext->ibucontext, vma);
+	if (!rdma_entry) {
+		pr_err_ratelimited("zrdma: pgoff[0x%lx] does not have valid entry\n",
+				   vma->vm_pgoff);
+		return -EINVAL;
+	}
+
+	entry = to_zxdh_mmap_entry(rdma_entry);
+
+	pfn = (entry->bar_offset +
+	       pci_resource_start(ucontext->zdev->rf->pcidev, 0)) >>
+	      PAGE_SHIFT;
+
+	switch (entry->mmap_flag) {
+	case ZXDH_MMAP_IO_NC:
+		ret = rdma_user_mmap_io(context, vma, pfn, PAGE_SIZE,
+					pgprot_noncached(vma->vm_page_prot),
+					rdma_entry);
+		break;
+	case ZXDH_MMAP_IO_NC_BY_SIZE:
+		ret = rdma_user_mmap_io(context, vma, pfn,
+					vma->vm_end - vma->vm_start,
+					pgprot_noncached(vma->vm_page_prot),
+					rdma_entry);
+		break;
+	case ZXDH_MMAP_IO_WC:
+		ret = rdma_user_mmap_io(context, vma, pfn, PAGE_SIZE,
+					pgprot_writecombine(vma->vm_page_prot),
+					rdma_entry);
+		break;
+	default:
+		pr_err("zrdma: unsupported mmap_flag[%d]\n",
+		       entry->mmap_flag);
+		ret = -EINVAL;
+	}
+
+	if (ret)
+		pr_err("zrdma: bar_offset [0x%llx] mmap_flag[%d] err[%d]\n",
+		       entry->bar_offset, entry->mmap_flag, ret);
+
+	rdma_user_mmap_entry_put(rdma_entry);
+
+	return ret;
+}
+
 const struct ib_device_ops zxdh_dev_ops = {
 	.owner = THIS_MODULE,
 	.driver_id = RDMA_DRIVER_ZRDMA,
 	.uverbs_abi_ver = ZXDH_ABI_VER,
 	.dealloc_driver = zxdh_ib_dealloc_device,
+	.alloc_pd = zxdh_alloc_pd,
+	.alloc_ucontext = zxdh_alloc_ucontext,
+	.dealloc_pd = zxdh_dealloc_pd,
+	.dealloc_ucontext = zxdh_dealloc_ucontext,
 	.query_device = zxdh_query_device,
 	.query_port = zxdh_query_port,
 	.query_pkey = zxdh_query_pkey,
 	.get_link_layer = zxdh_get_link_layer,
 	.get_port_immutable = zxdh_roce_port_immutable,
 	.get_dev_fw_str = zxdh_get_dev_fw_str,
+	.mmap = zxdh_mmap,
+	.mmap_free = zxdh_mmap_free,
+
+	INIT_RDMA_OBJ_SIZE(ib_pd, zxdh_pd, ibpd),
+	INIT_RDMA_OBJ_SIZE(ib_ucontext, zxdh_ucontext, ibucontext),
 };
-- 
2.43.5


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

* Re: [PATCH rdma v9 6/7] RDMA/zrdma: Add device probe and remove logic
  2026-11-03 12:56 ` [PATCH rdma v9 6/7] RDMA/zrdma: Add device probe and remove logic Yanze Zhang
@ 2026-11-03 13:17   ` sashiko-bot
  0 siblings, 0 replies; 15+ messages in thread
From: sashiko-bot @ 2026-11-03 13:17 UTC (permalink / raw)
  To: Yanze Zhang; +Cc: linux-rdma

> Implement the auxiliary bus probe and remove functions, including device
> initialization, hardware resource setup, and IB device registration.
> This replaces the stub probe from the initial skeleton patch. The file
> is modified rather than deleted, so every commit of the series builds on
> its own.
> 
> The device ops are installed right after ib_alloc_device(), so that the
> dealloc_driver hook is in place before any resource is taken. The hook
> releases the hardware resources and the address handle list lock, and it
> only destroys the lock when it was actually initialised. The pci device
> is owned by the PF driver, so the driver does not release it.
> 
> The netdev is bound to the IB device and the DMA capable device is
> handed to the core before the device is registered, so that the port
> queries read the netdev the auxiliary device belongs to and the core
> does not have to fall back to the kernel virtual address of the
> scatterlists.
> 
> Signed-off-by: Yanze Zhang <zhang.yanze@zte.com.cn>

Sashiko has reviewed this patch and found no issues.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261103125654.2707069-1-zhang.yanze@zte.com.cn?part=6


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

* Re: [PATCH rdma v9 3/7] RDMA/zrdma: Add internal headers and hardware register definitions
  2026-11-03 12:56 ` [PATCH rdma v9 3/7] RDMA/zrdma: Add internal headers and hardware register definitions Yanze Zhang
@ 2026-11-03 13:18   ` sashiko-bot
  0 siblings, 0 replies; 15+ messages in thread
From: sashiko-bot @ 2026-11-03 13:18 UTC (permalink / raw)
  To: Yanze Zhang; +Cc: linux-rdma

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] RDMA/zrdma: private duplication of PF driver auxiliary device structures
--

commit 41373c3ba84c37bb5af763979de45792b2597a0b
Author: Yanze Zhang <zhang.yanze@zte.com.cn>

RDMA/zrdma: Add internal headers and hardware register definitions

This commit adds internal header files defining driver device structures,
resource allocation helpers, and hardware limits for the ZTE DingHai RDMA
driver.

> diff --git a/drivers/infiniband/hw/zrdma/zrdma_main.h b/drivers/infiniband/hw/zrdma/zrdma_main.h
> new file mode 100644
> index 0000000000000..d65811735e74e
> --- /dev/null
> +++ b/drivers/infiniband/hw/zrdma/zrdma_main.h
> @@ -0,0 +1,177 @@

[ ... ]

> +struct zxdh_pci_f {

[ ... ]

> +	struct zxdh_sc_dev sc_dev;
> +	struct pci_dev *pcidev;
> +	struct zxdh_rdma_core_dev *zdev_info;
> +	struct zxdh_hw hw;
> +
> +	spinlock_t rsrc_lock; /* protects resource allocation arrays */
> +
> +	struct msix_entry *msix_entries;
> +	struct zxdh_gen_ops gen_ops;
> +	struct zxdh_device *zdev;
> +	u16 qp_index;
> +	bool net_irq_cap;
> +	int common_func_num_max;
> +	void *dh_dev;
> +};
> +
> +struct zxdh_device {
> +	struct ib_device ibdev;
> +	struct zxdh_pci_f *rf;
> +	struct net_device *netdev;
> +	struct list_head ah_list;
> +	struct mutex ah_list_lock; /* protects ah_list operations */
> +	u8 ibdev_status;
> +	u8 roce_mode : 1;
> +	enum init_completion_state init_state;
> +	struct zxdh_auxiliary_dev *zxdh_adev;

[ ... ]

> diff --git a/drivers/infiniband/hw/zrdma/zrdma_type.h b/drivers/infiniband/hw/zrdma/zrdma_type.h
> index ded4052453455..c6ad2be17c159 100644
> --- a/drivers/infiniband/hw/zrdma/zrdma_type.h
> +++ b/drivers/infiniband/hw/zrdma/zrdma_type.h
> @@ -21,6 +21,12 @@ enum zxdh_function_type {
>  	ZXDH_FUNCTION_TYPE_VF,
>  };
>  
> +/*
> + * The structures below describe the auxiliary device of the DingHai PF
> + * driver. Their layout has to match the definition of the PF driver
> + * exactly, because the probe path reads them through the auxiliary device
> + * that the PF driver provides.
> + */
>  struct zxdh_rdma_core_dev;

[Severity: Medium]
Should the cross-driver auxiliary device structures (struct
zxdh_auxiliary_dev, struct zxdh_rdma_core_dev, struct zxdh_rdma_core_ops, and
struct zxdh_rdma_if) be defined in a shared header under include/linux/
rather than privately duplicated in drivers/infiniband/hw/zrdma/zrdma_type.h
and referenced by struct zxdh_pci_f (zdev_info) and struct zxdh_device
(zxdh_adev) in drivers/infiniband/hw/zrdma/zrdma_main.h?

In a subsequent patch in the series, zxdh_probe() in
drivers/infiniband/hw/zrdma/zrdma_main.c casts the auxiliary_device pointer
via container_of(aux_dev, struct zxdh_auxiliary_dev, adev) and dereferences
zxdh_adev->rdma_ops and zxdh_adev->zxdh_info.

However, the in-tree DingHai PF driver under drivers/net/ethernet/zte/dinghai/
(en_pf.c, en_pf.h, dh_queue.h) does not define struct zxdh_auxiliary_dev or
struct zxdh_rdma_core_dev and does not register any auxiliary device. Relying
on manual struct layout matching across subsystems with untyped void *
placeholders (such as ops, parent, auxiliary_ops[18], and dh_dev) risks type
confusion and memory corruption if either driver changes.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261103125654.2707069-1-zhang.yanze@zte.com.cn?part=3

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

* Re: [PATCH rdma v9 2/7] RDMA/zrdma: Add core data structures and ABI definitions
  2026-11-03 12:56 ` [PATCH rdma v9 2/7] RDMA/zrdma: Add core data structures and ABI definitions Yanze Zhang
@ 2026-11-03 13:19   ` sashiko-bot
  0 siblings, 0 replies; 15+ messages in thread
From: sashiko-bot @ 2026-11-03 13:19 UTC (permalink / raw)
  To: Yanze Zhang; +Cc: linux-rdma

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] RDMA/zrdma: private untyped auxiliary device contract in zrdma_type.h
--

commit 32205a1a2a82a76eef58bea731ed3f41780dc2c9
Author: Yanze Zhang <zhang.yanze@zte.com.cn>

RDMA/zrdma: Add core data structures and ABI definitions

This commit adds core data structures, hardware control structures, and
user-space ABI definitions for the ZTE DingHai RDMA driver.

> diff --git a/drivers/infiniband/hw/zrdma/zrdma_type.h b/drivers/infiniband/hw/zrdma/zrdma_type.h
> new file mode 100644
> index 0000000000000..ded4052453455
> --- /dev/null
> +++ b/drivers/infiniband/hw/zrdma/zrdma_type.h
> @@ -0,0 +1,86 @@
[ ... ]
> +struct zxdh_rdma_core_dev;
> +
> +struct zxdh_rdma_core_ops {
> +	int (*request_reset)(struct zxdh_rdma_core_dev *cdev,
> +			     enum zxdh_rdma_reset_type reset_type);
> +	int (*zxdh_common_func)(void *in_param, void *out_param, u32 opcode);
> +};
[ ... ]
> +struct zxdh_rdma_core_dev {
> +	struct pci_dev *pdev;
> +	struct auxiliary_device *adev;
> +	u8 __iomem *hw_addr;
> +	int zdev_info_id;
> +	struct zxdh_rdma_ver_info ver;
> +	void *auxiliary_priv;
> +	enum zxdh_function_type ftype;
> +	u16 vport_id;
> +	u16 slot_id;
> +	enum zxdh_rdma_protocol rdma_protocol;
> +
> +	struct zxdh_qos_params qos_info;
> +	struct msix_entry *msix_entries;
> +	u16 msix_count;
> +	const struct zxdh_rdma_core_ops *ops;
> +	void *dh_dev;
> +};
> +
> +struct zxdh_rdma_if {
> +	void *(*get_rdma_netdev)(void *dh_dev);
> +};
> +
> +struct zxdh_auxiliary_dev {
> +	struct auxiliary_device adev;
> +	struct zxdh_rdma_core_dev *zxdh_info;
> +	struct zxdh_rdma_if *rdma_ops;
> +	void *ops;
> +	void *parent;
> +	s32 aux_id;
> +	void *auxiliary_ops[18];
> +};

[Severity: Medium]
As reported by Sashiko on v8 [1], defining the cross-driver auxiliary bus
structures (struct zxdh_auxiliary_dev, struct zxdh_rdma_core_dev, struct
zxdh_rdma_core_ops, and struct zxdh_rdma_if) in the driver-private header
drivers/infiniband/hw/zrdma/zrdma_type.h with untyped void * placeholder
fields bypasses compiler type and struct-layout verification between the
parent PCI PF driver and the RDMA auxiliary driver.

In commit 019e9ef26336 ("RDMA/zrdma: Add device probe and remove logic"),
zxdh_probe() binds to the dinghai10e.rdma_aux auxiliary device, converts
struct auxiliary_device *aux_dev via container_of(aux_dev, struct
zxdh_auxiliary_dev, adev) using this private definition, and invokes
zxdh_adev->rdma_ops->get_rdma_netdev(zxdh_adev->parent) and
zxdh_adev->zxdh_info->ops->zxdh_common_func(). Additionally, commit
41373c3ba84c ("RDMA/zrdma: Add internal headers and hardware register
definitions") notes that the struct layout must manually match the PF driver
definition, while the in-tree Ethernet driver under
drivers/net/ethernet/zte/dinghai/ does not define or register this auxiliary
device.

As documented in include/linux/auxiliary_bus.h, the container structure
embedding struct auxiliary_device and any shared interface structures must be
defined in a shared header under include/linux/ included by both the
registering PF driver and the consuming auxiliary driver. If the parent PF
driver and zrdma ever diverge in struct layout or callback signatures, could
container_of() or the untyped void * callbacks in zxdh_probe() corrupt memory
or call invalid function pointers?

Should these shared structures be moved to a common header under
include/linux/ with proper types (such as struct net_device * for
get_rdma_netdev() and typed parameters instead of void *ops, void *parent,
void *auxiliary_ops[18], void *dh_dev, and zxdh_common_func()), alongside the
corresponding auxiliary device registration in the in-tree parent driver?

[1] https://lore.kernel.org/r/20261102082026.2645777-3-zhang.yanze@zte.com.cn

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261103125654.2707069-1-zhang.yanze@zte.com.cn?part=2

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

* Re: [PATCH rdma v9 1/7] RDMA/zrdma: Add build infrastructure and module skeleton
  2026-11-03 12:56 ` [PATCH rdma v9 1/7] RDMA/zrdma: Add build infrastructure and module skeleton Yanze Zhang
@ 2026-11-03 13:20   ` sashiko-bot
  0 siblings, 0 replies; 15+ messages in thread
From: sashiko-bot @ 2026-11-03 13:20 UTC (permalink / raw)
  To: Yanze Zhang; +Cc: linux-rdma

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Low] RDMA/zrdma: open-coded zrdma_module_init() instead of module_auxiliary_driver()
--

commit 752d6c4a965c859c6d742178ece9515bf23454aa
Author: Yanze Zhang <zhang.yanze@zte.com.cn>

RDMA/zrdma: Add build infrastructure and module skeleton

This commit adds the MAINTAINERS entry, Kconfig, Makefile, and a minimal
auxiliary driver module skeleton for the ZTE DingHai RDMA driver.

> diff --git a/drivers/infiniband/hw/zrdma/zrdma_main.c b/drivers/infiniband/hw/zrdma/zrdma_main.c
> new file mode 100644
> index 0000000000000..80856c7ff6b2a
> --- /dev/null
> +++ b/drivers/infiniband/hw/zrdma/zrdma_main.c

[ ... ]

> +static struct auxiliary_driver zxdh_auxiliary_drv = {
> +	.name = "rdma_aux",
> +	.id_table = zxdh_auxiliary_id_table,
> +	.probe = zxdh_probe,
> +	.remove = zxdh_remove,
> +};
> +
> +static int __init zrdma_module_init(void)
> +{
> +	return auxiliary_driver_register(&zxdh_auxiliary_drv);
> +}
> +
> +static void __exit zrdma_module_exit(void)
> +{
> +	auxiliary_driver_unregister(&zxdh_auxiliary_drv);
> +}
> +
> +module_init(zrdma_module_init);
> +module_exit(zrdma_module_exit);

[Severity: Low]
As reported by Sashiko on v8 [1], this isn't a bug, but since
zrdma_module_init() and zrdma_module_exit() only call
auxiliary_driver_register() and auxiliary_driver_unregister() on
zxdh_auxiliary_drv (including at the end of the patch series), could these
wrappers be replaced with module_auxiliary_driver(zxdh_auxiliary_drv) from
include/linux/auxiliary_bus.h?

[1] https://lore.kernel.org/r/20261102082026.2645777-2-zhang.yanze@zte.com.cn

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261103125654.2707069-1-zhang.yanze@zte.com.cn?part=1

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

* Re: [PATCH rdma v9 4/7] RDMA/zrdma: Add hardware resource initialization and verbs skeleton
  2026-11-03 12:56 ` [PATCH rdma v9 4/7] RDMA/zrdma: Add hardware resource initialization and verbs skeleton Yanze Zhang
@ 2026-11-03 13:21   ` sashiko-bot
  0 siblings, 0 replies; 15+ messages in thread
From: sashiko-bot @ 2026-11-03 13:21 UTC (permalink / raw)
  To: Yanze Zhang; +Cc: linux-rdma

> Implement hardware resource initialization logic and provide a minimal
> but functional verbs layer skeleton. This includes basic device
> registration with the minimal set of device ops (owner, driver_id,
> uverbs_abi_ver), to satisfy the requirement that the driver must be
> functional and have a valid driver ID.
> 
> The hardware resources of the driver are held in a single allocation,
> which carries the allocation bitmaps of the resource pools. The first
> entry of the memory region, protection domain, queue pair, address
> handle and multicast group pools is reserved.
> 
> The device ops are exported so that the probe path can install them
> right after ib_alloc_device(). When the resource memory cannot be
> allocated, the 8K index counter array is released with a cleared
> pointer, so that the dealloc hook does not free the same allocation
> twice.
> 
> Signed-off-by: Yanze Zhang <zhang.yanze@zte.com.cn>

Sashiko has reviewed this patch and found no issues.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261103125654.2707069-1-zhang.yanze@zte.com.cn?part=4


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

* Re: [PATCH rdma v9 7/7] RDMA/zrdma: Implement context, PD, and mmap operations
  2026-11-03 12:56 ` [PATCH rdma v9 7/7] RDMA/zrdma: Implement context, PD, and mmap operations Yanze Zhang
@ 2026-11-03 13:23   ` sashiko-bot
  0 siblings, 0 replies; 15+ messages in thread
From: sashiko-bot @ 2026-11-03 13:23 UTC (permalink / raw)
  To: Yanze Zhang; +Cc: linux-rdma

> Add implementation for allocation/deallocation of Protection Domains (PD),
> User Contexts, and memory mapping (mmap) for doorbells.
> 
> The SRQ doorbell area is not page aligned on 16K and 64K page systems, so
> the mapping length is extended to the page boundary and the size
> reported to userspace is the very same length. The V1 and V2 contexts do
> not know the size of the SRQ doorbell area, so only the first page is
> mapped for them.
> 
> Signed-off-by: Yanze Zhang <zhang.yanze@zte.com.cn>

Sashiko has reviewed this patch and found no issues.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261103125654.2707069-1-zhang.yanze@zte.com.cn?part=7


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

* Re: [PATCH rdma v9 5/7] RDMA/zrdma: Implement device and port query operations
  2026-11-03 12:56 ` [PATCH rdma v9 5/7] RDMA/zrdma: Implement device and port query operations Yanze Zhang
@ 2026-11-03 13:25   ` sashiko-bot
  0 siblings, 0 replies; 15+ messages in thread
From: sashiko-bot @ 2026-11-03 13:25 UTC (permalink / raw)
  To: Yanze Zhang; +Cc: linux-rdma

> Add implementation for querying device attributes, port attributes,
> PKey, and link layer information. Also include firmware version string
> retrieval.
> 
> The device attributes report the limits of the hardware, the vendor id
> and the firmware version, which is taken from the driver info of the
> network device. The port attributes report the state and the speed of
> the port, which is taken from the network device on every query. The
> immutable port information describes the RoCE encapsulation of the
> port.
> 
> Signed-off-by: Yanze Zhang <zhang.yanze@zte.com.cn>

Sashiko has reviewed this patch and found no issues.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261103125654.2707069-1-zhang.yanze@zte.com.cn?part=5


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

end of thread, other threads:[~2026-11-03 13:25 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-03 12:56 [PATCH rdma v9 0/7] Add ZTE DingHai Ethernet Protocol Driver for RDMA Yanze Zhang
2026-11-03 12:56 ` [PATCH rdma v9 1/7] RDMA/zrdma: Add build infrastructure and module skeleton Yanze Zhang
2026-11-03 13:20   ` sashiko-bot
2026-11-03 12:56 ` [PATCH rdma v9 2/7] RDMA/zrdma: Add core data structures and ABI definitions Yanze Zhang
2026-11-03 13:19   ` sashiko-bot
2026-11-03 12:56 ` [PATCH rdma v9 3/7] RDMA/zrdma: Add internal headers and hardware register definitions Yanze Zhang
2026-11-03 13:18   ` sashiko-bot
2026-11-03 12:56 ` [PATCH rdma v9 4/7] RDMA/zrdma: Add hardware resource initialization and verbs skeleton Yanze Zhang
2026-11-03 13:21   ` sashiko-bot
2026-11-03 12:56 ` [PATCH rdma v9 5/7] RDMA/zrdma: Implement device and port query operations Yanze Zhang
2026-11-03 13:25   ` sashiko-bot
2026-11-03 12:56 ` [PATCH rdma v9 6/7] RDMA/zrdma: Add device probe and remove logic Yanze Zhang
2026-11-03 13:17   ` sashiko-bot
2026-11-03 12:56 ` [PATCH rdma v9 7/7] RDMA/zrdma: Implement context, PD, and mmap operations Yanze Zhang
2026-11-03 13:23   ` sashiko-bot

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