18d765af5SAbhijit Gangurde // SPDX-License-Identifier: GPL-2.0 28d765af5SAbhijit Gangurde /* Copyright (C) 2018-2025, Advanced Micro Devices, Inc. */ 38d765af5SAbhijit Gangurde 48d765af5SAbhijit Gangurde #include <linux/module.h> 58d765af5SAbhijit Gangurde #include <linux/printk.h> 68d765af5SAbhijit Gangurde #include <net/addrconf.h> 78d765af5SAbhijit Gangurde 88d765af5SAbhijit Gangurde #include "ionic_ibdev.h" 98d765af5SAbhijit Gangurde 108d765af5SAbhijit Gangurde #define DRIVER_DESCRIPTION "AMD Pensando RoCE HCA driver" 118d765af5SAbhijit Gangurde #define DEVICE_DESCRIPTION "AMD Pensando RoCE HCA" 128d765af5SAbhijit Gangurde 138d765af5SAbhijit Gangurde MODULE_AUTHOR("Allen Hubbe <allen.hubbe@amd.com>"); 148d765af5SAbhijit Gangurde MODULE_DESCRIPTION(DRIVER_DESCRIPTION); 158d765af5SAbhijit Gangurde MODULE_LICENSE("GPL"); 168d765af5SAbhijit Gangurde MODULE_IMPORT_NS("NET_IONIC"); 178d765af5SAbhijit Gangurde 18e8521822SAbhijit Gangurde static const struct ib_device_ops ionic_dev_ops = { 19e8521822SAbhijit Gangurde .owner = THIS_MODULE, 20e8521822SAbhijit Gangurde .driver_id = RDMA_DRIVER_IONIC, 21e8521822SAbhijit Gangurde .uverbs_abi_ver = IONIC_ABI_VERSION, 22e8521822SAbhijit Gangurde 23e8521822SAbhijit Gangurde .alloc_ucontext = ionic_alloc_ucontext, 24e8521822SAbhijit Gangurde .dealloc_ucontext = ionic_dealloc_ucontext, 25e8521822SAbhijit Gangurde .mmap = ionic_mmap, 26e8521822SAbhijit Gangurde .mmap_free = ionic_mmap_free, 27e8521822SAbhijit Gangurde .alloc_pd = ionic_alloc_pd, 28e8521822SAbhijit Gangurde .dealloc_pd = ionic_dealloc_pd, 29e8521822SAbhijit Gangurde .create_ah = ionic_create_ah, 30e8521822SAbhijit Gangurde .query_ah = ionic_query_ah, 31e8521822SAbhijit Gangurde .destroy_ah = ionic_destroy_ah, 32e8521822SAbhijit Gangurde .create_user_ah = ionic_create_ah, 33e8521822SAbhijit Gangurde .get_dma_mr = ionic_get_dma_mr, 34e8521822SAbhijit Gangurde .reg_user_mr = ionic_reg_user_mr, 35e8521822SAbhijit Gangurde .reg_user_mr_dmabuf = ionic_reg_user_mr_dmabuf, 36e8521822SAbhijit Gangurde .dereg_mr = ionic_dereg_mr, 37e8521822SAbhijit Gangurde .alloc_mr = ionic_alloc_mr, 38e8521822SAbhijit Gangurde .map_mr_sg = ionic_map_mr_sg, 39e8521822SAbhijit Gangurde .alloc_mw = ionic_alloc_mw, 40e8521822SAbhijit Gangurde .dealloc_mw = ionic_dealloc_mw, 41e8521822SAbhijit Gangurde .create_cq = ionic_create_cq, 42e8521822SAbhijit Gangurde .destroy_cq = ionic_destroy_cq, 43e8521822SAbhijit Gangurde .create_qp = ionic_create_qp, 44e8521822SAbhijit Gangurde .modify_qp = ionic_modify_qp, 45e8521822SAbhijit Gangurde .query_qp = ionic_query_qp, 46e8521822SAbhijit Gangurde .destroy_qp = ionic_destroy_qp, 47e8521822SAbhijit Gangurde 48*b83c6205SAbhijit Gangurde .post_send = ionic_post_send, 49*b83c6205SAbhijit Gangurde .post_recv = ionic_post_recv, 50*b83c6205SAbhijit Gangurde .poll_cq = ionic_poll_cq, 51*b83c6205SAbhijit Gangurde .req_notify_cq = ionic_req_notify_cq, 52*b83c6205SAbhijit Gangurde 53e8521822SAbhijit Gangurde INIT_RDMA_OBJ_SIZE(ib_ucontext, ionic_ctx, ibctx), 54e8521822SAbhijit Gangurde INIT_RDMA_OBJ_SIZE(ib_pd, ionic_pd, ibpd), 55e8521822SAbhijit Gangurde INIT_RDMA_OBJ_SIZE(ib_ah, ionic_ah, ibah), 56e8521822SAbhijit Gangurde INIT_RDMA_OBJ_SIZE(ib_cq, ionic_vcq, ibcq), 57e8521822SAbhijit Gangurde INIT_RDMA_OBJ_SIZE(ib_qp, ionic_qp, ibqp), 58e8521822SAbhijit Gangurde INIT_RDMA_OBJ_SIZE(ib_mw, ionic_mr, ibmw), 59e8521822SAbhijit Gangurde }; 60e8521822SAbhijit Gangurde 61f3bdbd42SAbhijit Gangurde static void ionic_init_resids(struct ionic_ibdev *dev) 62f3bdbd42SAbhijit Gangurde { 63f3bdbd42SAbhijit Gangurde ionic_resid_init(&dev->inuse_cqid, dev->lif_cfg.cq_count); 64f3bdbd42SAbhijit Gangurde dev->half_cqid_udma_shift = 65f3bdbd42SAbhijit Gangurde order_base_2(dev->lif_cfg.cq_count / dev->lif_cfg.udma_count); 66f3bdbd42SAbhijit Gangurde ionic_resid_init(&dev->inuse_pdid, IONIC_MAX_PD); 67f3bdbd42SAbhijit Gangurde ionic_resid_init(&dev->inuse_ahid, dev->lif_cfg.nahs_per_lif); 68f3bdbd42SAbhijit Gangurde ionic_resid_init(&dev->inuse_mrid, dev->lif_cfg.nmrs_per_lif); 69f3bdbd42SAbhijit Gangurde /* skip reserved lkey */ 70f3bdbd42SAbhijit Gangurde dev->next_mrkey = 1; 71f3bdbd42SAbhijit Gangurde ionic_resid_init(&dev->inuse_qpid, dev->lif_cfg.qp_count); 72f3bdbd42SAbhijit Gangurde /* skip reserved SMI and GSI qpids */ 73f3bdbd42SAbhijit Gangurde dev->half_qpid_udma_shift = 74f3bdbd42SAbhijit Gangurde order_base_2(dev->lif_cfg.qp_count / dev->lif_cfg.udma_count); 75f3bdbd42SAbhijit Gangurde ionic_resid_init(&dev->inuse_dbid, dev->lif_cfg.dbid_count); 76f3bdbd42SAbhijit Gangurde } 77f3bdbd42SAbhijit Gangurde 78f3bdbd42SAbhijit Gangurde static void ionic_destroy_resids(struct ionic_ibdev *dev) 79f3bdbd42SAbhijit Gangurde { 80f3bdbd42SAbhijit Gangurde ionic_resid_destroy(&dev->inuse_cqid); 81f3bdbd42SAbhijit Gangurde ionic_resid_destroy(&dev->inuse_pdid); 82f3bdbd42SAbhijit Gangurde ionic_resid_destroy(&dev->inuse_ahid); 83f3bdbd42SAbhijit Gangurde ionic_resid_destroy(&dev->inuse_mrid); 84f3bdbd42SAbhijit Gangurde ionic_resid_destroy(&dev->inuse_qpid); 85f3bdbd42SAbhijit Gangurde ionic_resid_destroy(&dev->inuse_dbid); 86f3bdbd42SAbhijit Gangurde } 87f3bdbd42SAbhijit Gangurde 888d765af5SAbhijit Gangurde static void ionic_destroy_ibdev(struct ionic_ibdev *dev) 898d765af5SAbhijit Gangurde { 90f3bdbd42SAbhijit Gangurde ionic_kill_rdma_admin(dev, false); 918d765af5SAbhijit Gangurde ib_unregister_device(&dev->ibdev); 92f3bdbd42SAbhijit Gangurde ionic_destroy_rdma_admin(dev); 93f3bdbd42SAbhijit Gangurde ionic_destroy_resids(dev); 94e8521822SAbhijit Gangurde WARN_ON(!xa_empty(&dev->qp_tbl)); 95e8521822SAbhijit Gangurde xa_destroy(&dev->qp_tbl); 96f3bdbd42SAbhijit Gangurde WARN_ON(!xa_empty(&dev->cq_tbl)); 97f3bdbd42SAbhijit Gangurde xa_destroy(&dev->cq_tbl); 988d765af5SAbhijit Gangurde ib_dealloc_device(&dev->ibdev); 998d765af5SAbhijit Gangurde } 1008d765af5SAbhijit Gangurde 1018d765af5SAbhijit Gangurde static struct ionic_ibdev *ionic_create_ibdev(struct ionic_aux_dev *ionic_adev) 1028d765af5SAbhijit Gangurde { 1038d765af5SAbhijit Gangurde struct ib_device *ibdev; 1048d765af5SAbhijit Gangurde struct ionic_ibdev *dev; 1058d765af5SAbhijit Gangurde struct net_device *ndev; 1068d765af5SAbhijit Gangurde int rc; 1078d765af5SAbhijit Gangurde 1088d765af5SAbhijit Gangurde dev = ib_alloc_device(ionic_ibdev, ibdev); 1098d765af5SAbhijit Gangurde if (!dev) 1108d765af5SAbhijit Gangurde return ERR_PTR(-EINVAL); 1118d765af5SAbhijit Gangurde 1128d765af5SAbhijit Gangurde ionic_fill_lif_cfg(ionic_adev->lif, &dev->lif_cfg); 1138d765af5SAbhijit Gangurde 114e8521822SAbhijit Gangurde xa_init_flags(&dev->qp_tbl, GFP_ATOMIC); 115f3bdbd42SAbhijit Gangurde xa_init_flags(&dev->cq_tbl, GFP_ATOMIC); 116f3bdbd42SAbhijit Gangurde 117f3bdbd42SAbhijit Gangurde ionic_init_resids(dev); 118f3bdbd42SAbhijit Gangurde 119f3bdbd42SAbhijit Gangurde rc = ionic_rdma_reset_devcmd(dev); 120f3bdbd42SAbhijit Gangurde if (rc) 121f3bdbd42SAbhijit Gangurde goto err_reset; 122f3bdbd42SAbhijit Gangurde 123f3bdbd42SAbhijit Gangurde rc = ionic_create_rdma_admin(dev); 124f3bdbd42SAbhijit Gangurde if (rc) 125f3bdbd42SAbhijit Gangurde goto err_admin; 126f3bdbd42SAbhijit Gangurde 1278d765af5SAbhijit Gangurde ibdev = &dev->ibdev; 1288d765af5SAbhijit Gangurde ibdev->dev.parent = dev->lif_cfg.hwdev; 1298d765af5SAbhijit Gangurde 1308d765af5SAbhijit Gangurde strscpy(ibdev->name, "ionic_%d", IB_DEVICE_NAME_MAX); 1318d765af5SAbhijit Gangurde strscpy(ibdev->node_desc, DEVICE_DESCRIPTION, IB_DEVICE_NODE_DESC_MAX); 1328d765af5SAbhijit Gangurde 1338d765af5SAbhijit Gangurde ibdev->node_type = RDMA_NODE_IB_CA; 1348d765af5SAbhijit Gangurde ibdev->phys_port_cnt = 1; 1358d765af5SAbhijit Gangurde 1368d765af5SAbhijit Gangurde /* the first two eq are reserved for async events */ 1378d765af5SAbhijit Gangurde ibdev->num_comp_vectors = dev->lif_cfg.eq_count - 2; 1388d765af5SAbhijit Gangurde 1398d765af5SAbhijit Gangurde ndev = ionic_lif_netdev(ionic_adev->lif); 1408d765af5SAbhijit Gangurde addrconf_ifid_eui48((u8 *)&ibdev->node_guid, ndev); 1418d765af5SAbhijit Gangurde rc = ib_device_set_netdev(ibdev, ndev, 1); 1428d765af5SAbhijit Gangurde /* ionic_lif_netdev() returns ndev with refcount held */ 1438d765af5SAbhijit Gangurde dev_put(ndev); 1448d765af5SAbhijit Gangurde if (rc) 1458d765af5SAbhijit Gangurde goto err_admin; 1468d765af5SAbhijit Gangurde 147e8521822SAbhijit Gangurde ib_set_device_ops(&dev->ibdev, &ionic_dev_ops); 148e8521822SAbhijit Gangurde 1498d765af5SAbhijit Gangurde rc = ib_register_device(ibdev, "ionic_%d", ibdev->dev.parent); 1508d765af5SAbhijit Gangurde if (rc) 1518d765af5SAbhijit Gangurde goto err_register; 1528d765af5SAbhijit Gangurde 1538d765af5SAbhijit Gangurde return dev; 1548d765af5SAbhijit Gangurde 1558d765af5SAbhijit Gangurde err_register: 1568d765af5SAbhijit Gangurde err_admin: 157f3bdbd42SAbhijit Gangurde ionic_kill_rdma_admin(dev, false); 158f3bdbd42SAbhijit Gangurde ionic_destroy_rdma_admin(dev); 159f3bdbd42SAbhijit Gangurde err_reset: 160f3bdbd42SAbhijit Gangurde ionic_destroy_resids(dev); 161e8521822SAbhijit Gangurde xa_destroy(&dev->qp_tbl); 162f3bdbd42SAbhijit Gangurde xa_destroy(&dev->cq_tbl); 1638d765af5SAbhijit Gangurde ib_dealloc_device(&dev->ibdev); 1648d765af5SAbhijit Gangurde 1658d765af5SAbhijit Gangurde return ERR_PTR(rc); 1668d765af5SAbhijit Gangurde } 1678d765af5SAbhijit Gangurde 1688d765af5SAbhijit Gangurde static int ionic_aux_probe(struct auxiliary_device *adev, 1698d765af5SAbhijit Gangurde const struct auxiliary_device_id *id) 1708d765af5SAbhijit Gangurde { 1718d765af5SAbhijit Gangurde struct ionic_aux_dev *ionic_adev; 1728d765af5SAbhijit Gangurde struct ionic_ibdev *dev; 1738d765af5SAbhijit Gangurde 1748d765af5SAbhijit Gangurde ionic_adev = container_of(adev, struct ionic_aux_dev, adev); 1758d765af5SAbhijit Gangurde dev = ionic_create_ibdev(ionic_adev); 1768d765af5SAbhijit Gangurde if (IS_ERR(dev)) 1778d765af5SAbhijit Gangurde return dev_err_probe(&adev->dev, PTR_ERR(dev), 1788d765af5SAbhijit Gangurde "Failed to register ibdev\n"); 1798d765af5SAbhijit Gangurde 1808d765af5SAbhijit Gangurde auxiliary_set_drvdata(adev, dev); 1818d765af5SAbhijit Gangurde ibdev_dbg(&dev->ibdev, "registered\n"); 1828d765af5SAbhijit Gangurde 1838d765af5SAbhijit Gangurde return 0; 1848d765af5SAbhijit Gangurde } 1858d765af5SAbhijit Gangurde 1868d765af5SAbhijit Gangurde static void ionic_aux_remove(struct auxiliary_device *adev) 1878d765af5SAbhijit Gangurde { 1888d765af5SAbhijit Gangurde struct ionic_ibdev *dev = auxiliary_get_drvdata(adev); 1898d765af5SAbhijit Gangurde 1908d765af5SAbhijit Gangurde dev_dbg(&adev->dev, "unregister ibdev\n"); 1918d765af5SAbhijit Gangurde ionic_destroy_ibdev(dev); 1928d765af5SAbhijit Gangurde dev_dbg(&adev->dev, "unregistered\n"); 1938d765af5SAbhijit Gangurde } 1948d765af5SAbhijit Gangurde 1958d765af5SAbhijit Gangurde static const struct auxiliary_device_id ionic_aux_id_table[] = { 1968d765af5SAbhijit Gangurde { .name = "ionic.rdma", }, 1978d765af5SAbhijit Gangurde {}, 1988d765af5SAbhijit Gangurde }; 1998d765af5SAbhijit Gangurde 2008d765af5SAbhijit Gangurde MODULE_DEVICE_TABLE(auxiliary, ionic_aux_id_table); 2018d765af5SAbhijit Gangurde 2028d765af5SAbhijit Gangurde static struct auxiliary_driver ionic_aux_r_driver = { 2038d765af5SAbhijit Gangurde .name = "rdma", 2048d765af5SAbhijit Gangurde .probe = ionic_aux_probe, 2058d765af5SAbhijit Gangurde .remove = ionic_aux_remove, 2068d765af5SAbhijit Gangurde .id_table = ionic_aux_id_table, 2078d765af5SAbhijit Gangurde }; 2088d765af5SAbhijit Gangurde 2098d765af5SAbhijit Gangurde static int __init ionic_mod_init(void) 2108d765af5SAbhijit Gangurde { 2118d765af5SAbhijit Gangurde int rc; 2128d765af5SAbhijit Gangurde 213e8521822SAbhijit Gangurde ionic_evt_workq = create_workqueue(KBUILD_MODNAME "-evt"); 214f3bdbd42SAbhijit Gangurde if (!ionic_evt_workq) 215f3bdbd42SAbhijit Gangurde return -ENOMEM; 216f3bdbd42SAbhijit Gangurde 2178d765af5SAbhijit Gangurde rc = auxiliary_driver_register(&ionic_aux_r_driver); 2188d765af5SAbhijit Gangurde if (rc) 2198d765af5SAbhijit Gangurde goto err_aux; 2208d765af5SAbhijit Gangurde 2218d765af5SAbhijit Gangurde return 0; 2228d765af5SAbhijit Gangurde 2238d765af5SAbhijit Gangurde err_aux: 224f3bdbd42SAbhijit Gangurde destroy_workqueue(ionic_evt_workq); 225f3bdbd42SAbhijit Gangurde 2268d765af5SAbhijit Gangurde return rc; 2278d765af5SAbhijit Gangurde } 2288d765af5SAbhijit Gangurde 2298d765af5SAbhijit Gangurde static void __exit ionic_mod_exit(void) 2308d765af5SAbhijit Gangurde { 2318d765af5SAbhijit Gangurde auxiliary_driver_unregister(&ionic_aux_r_driver); 232f3bdbd42SAbhijit Gangurde destroy_workqueue(ionic_evt_workq); 2338d765af5SAbhijit Gangurde } 2348d765af5SAbhijit Gangurde 2358d765af5SAbhijit Gangurde module_init(ionic_mod_init); 2368d765af5SAbhijit Gangurde module_exit(ionic_mod_exit); 237