[PATCH rdma v5 5/7] RDMA/zrdma: Add device probe and remove logic

Yanze Zhang <[email protected]>
Newsgroups org.kernel.vger.linux-rdma,org.kernel.vger.linux-kernel
Message-ID <[email protected]>
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.

Signed-off-by: Yanze Zhang <[email protected]>
---
 drivers/infiniband/hw/zrdma/zrdma_main.c | 251 +++++++++++++++++++++--
 1 file changed, 237 insertions(+), 14 deletions(-)

diff --git a/drivers/infiniband/hw/zrdma/zrdma_main.c b/drivers/infiniband/hw/zrdma/zrdma_main.c
index 7954d86573e2..c181736a9641 100644
--- a/drivers/infiniband/hw/zrdma/zrdma_main.c
+++ b/drivers/infiniband/hw/zrdma/zrdma_main.c
@@ -6,36 +6,246 @@
 
 #include <linux/module.h>
 #include <linux/auxiliary_bus.h>
+#include <linux/types.h>
+#include <linux/netdevice.h>
+#include <linux/workqueue.h>
+#include <rdma/ib_verbs.h>
 
-#define ZXDH_PF_NAME "dinghai10e"
-#define ZXDH_RDMA_DEV_NAME "rdma_aux"
+#include "zrdma_main.h"
 
-MODULE_LICENSE("Dual BSD/GPL");
+MODULE_ALIAS("zrdma");
 MODULE_AUTHOR("Yanze Zhang <[email protected]>");
 MODULE_DESCRIPTION("ZTE Ethernet Protocol Driver for RDMA");
+MODULE_LICENSE("Dual BSD/GPL");
 
-static const struct auxiliary_device_id zxdh_auxiliary_id_table[] = {
-	{
-		.name = ZXDH_PF_NAME "." ZXDH_RDMA_DEV_NAME,
-	},
-	{},
-};
+LIST_HEAD(zxdh_handlers);
+DEFINE_SPINLOCK(zxdh_handler_lock);
 
-MODULE_DEVICE_TABLE(auxiliary, zxdh_auxiliary_id_table);
+static struct mutex rdma_name_lock;
+static struct list_head zxdh_rdma_list;
+
+static void zxdh_add_handler(struct zxdh_handler *hdl)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&zxdh_handler_lock, flags);
+	list_add(&hdl->list, &zxdh_handlers);
+	spin_unlock_irqrestore(&zxdh_handler_lock, flags);
+}
+
+void zxdh_del_handler(struct zxdh_handler *hdl)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&zxdh_handler_lock, flags);
+	list_del(&hdl->list);
+	spin_unlock_irqrestore(&zxdh_handler_lock, flags);
+}
+
+int zxdh_get_del_rdma_name(const char *sbdf, char *name)
+{
+	struct zxdh_rdma_node *pos, *tmp;
+	u8 len = 0;
+
+	if (!sbdf || !name)
+		return -EINVAL;
+
+	if (strlen(name) > IB_DEVICE_NAME_MAX) {
+		pr_err("zrdma: name len out of range\n");
+		return -EINVAL;
+	}
+
+	mutex_lock(&rdma_name_lock);
+	list_for_each_entry_safe(pos, tmp, &zxdh_rdma_list, list) {
+		len = strlen(pos->sbdf);
+		if (strlen(sbdf) == len) {
+			if (strncasecmp(sbdf, pos->sbdf, len) == 0) {
+				snprintf(name, IB_DEVICE_NAME_MAX, "%s",
+					 pos->name);
+				list_del(&pos->list);
+				kfree(pos);
+				mutex_unlock(&rdma_name_lock);
+				return 0;
+			}
+		}
+	}
+	mutex_unlock(&rdma_name_lock);
+	return -ENOENT;
+}
+
+static void zxdh_get_net_irq_cap(struct zxdh_pci_f *rf)
+{
+	u32 opcode = 0;
+
+	if (rf->gen_ops.zxdh_common_func) {
+		opcode = rf->gen_ops.zxdh_common_func(NULL, NULL,
+						      ZXDH_FUNC_NUM_REQUIRE);
+		if (opcode > ZXDH_FUNC_IRQ_FREE && opcode != 0xFF)
+			rf->net_irq_cap = true;
+	}
+}
+
+static void zxdh_get_common_func_num_max(struct zxdh_pci_f *rf)
+{
+	u32 num_max = 0;
+
+	if (rf->gen_ops.zxdh_common_func) {
+		num_max = rf->gen_ops.zxdh_common_func(NULL, NULL,
+						       ZXDH_FUNC_NUM_REQUIRE);
+		if (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;
+	rf->sc_dev.max_ceqs = (rf->msix_count - 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;
+	rf->drv_np_cap =
+		(bool)FIELD_GET(ZXDH_RDMA_COMM_FUNC, zdev_info->ver.support);
+	if (rf->drv_np_cap == 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_net_irq_cap(rf);
+	zxdh_get_common_func_num_max(rf);
+
+	rf->zdev = zdev;
+
+	INIT_LIST_HEAD(&zdev->ah_list);
+	mutex_init(&zdev->ah_list_lock);
+	zdev->init_state = INITIAL_STATE;
+	zdev->roce_mode = true;
+}
 
 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_handler *hdl;
+	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;
+	}
+
+	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;
+
+	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);
+
+	hdl = kzalloc_obj(*hdl);
+	if (!hdl) {
+		kfree(zdev->rf);
+		ib_dealloc_device(&zdev->ibdev);
+		return -ENOMEM;
+	}
+
+	hdl->zdev = zdev;
+	zdev->hdl = hdl;
+	zdev->netdev_speed = SPEED_UNKNOWN;
+
+	rf = zdev->rf;
+	err = zxdh_ctrl_init_hw(rf);
+	if (err)
+		goto err_ctrl_init;
+
+	zxdh_add_handler(hdl);
+
+	err = zxdh_ib_register_device(zdev);
+	if (err)
+		goto err_ib_reg;
+
+	dev_set_drvdata(&aux_dev->dev, zdev);
+
 	return 0;
+
+err_ib_reg:
+	zxdh_del_handler(hdl);
+err_ctrl_init:
+	kfree(zdev->rf);
+	kfree(hdl);
+	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;
+	}
+
+	ib_unregister_device(&zdev->ibdev);
+	zxdh_del_handler(zdev->hdl);
+
+	kfree(zdev->rf);
+	kfree(zdev->hdl);
+	ib_dealloc_device(&zdev->ibdev);
+}
+
+static void zxdh_shutdown(struct auxiliary_device *aux_dev)
+{
+	zxdh_remove(aux_dev);
 }
 
+static const struct auxiliary_device_id zxdh_auxiliary_id_table[] = {
+	{
+		.name = ZXDH_PF_NAME "." ZXDH_RDMA_DEV_NAME,
+	},
+	{},
+};
+
+MODULE_DEVICE_TABLE(auxiliary, zxdh_auxiliary_id_table);
+
 static struct auxiliary_driver zxdh_auxiliary_drv = {
 	.driver = {
 		.name = ZXDH_RDMA_DEV_NAME,
@@ -43,16 +253,29 @@ static struct auxiliary_driver zxdh_auxiliary_drv = {
 	.id_table = zxdh_auxiliary_id_table,
 	.probe = zxdh_probe,
 	.remove = zxdh_remove,
+	.shutdown = zxdh_shutdown,
 };
 
 static int __init zrdma_module_init(void)
 {
-	return auxiliary_driver_register(&zxdh_auxiliary_drv);
+	int ret;
+
+	INIT_LIST_HEAD(&zxdh_rdma_list);
+	mutex_init(&rdma_name_lock);
+
+	ret = auxiliary_driver_register(&zxdh_auxiliary_drv);
+	if (ret) {
+		pr_err("zrdma: failed to register auxiliary driver\n");
+		return ret;
+	}
+
+	return 0;
 }
 
 static void __exit zrdma_module_exit(void)
 {
 	auxiliary_driver_unregister(&zxdh_auxiliary_drv);
+	mutex_destroy(&rdma_name_lock);
 }
 
 module_init(zrdma_module_init);
-- 
2.27.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.