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 18*f3bdbd42SAbhijit Gangurde static void ionic_init_resids(struct ionic_ibdev *dev) 19*f3bdbd42SAbhijit Gangurde { 20*f3bdbd42SAbhijit Gangurde ionic_resid_init(&dev->inuse_cqid, dev->lif_cfg.cq_count); 21*f3bdbd42SAbhijit Gangurde dev->half_cqid_udma_shift = 22*f3bdbd42SAbhijit Gangurde order_base_2(dev->lif_cfg.cq_count / dev->lif_cfg.udma_count); 23*f3bdbd42SAbhijit Gangurde ionic_resid_init(&dev->inuse_pdid, IONIC_MAX_PD); 24*f3bdbd42SAbhijit Gangurde ionic_resid_init(&dev->inuse_ahid, dev->lif_cfg.nahs_per_lif); 25*f3bdbd42SAbhijit Gangurde ionic_resid_init(&dev->inuse_mrid, dev->lif_cfg.nmrs_per_lif); 26*f3bdbd42SAbhijit Gangurde /* skip reserved lkey */ 27*f3bdbd42SAbhijit Gangurde dev->next_mrkey = 1; 28*f3bdbd42SAbhijit Gangurde ionic_resid_init(&dev->inuse_qpid, dev->lif_cfg.qp_count); 29*f3bdbd42SAbhijit Gangurde /* skip reserved SMI and GSI qpids */ 30*f3bdbd42SAbhijit Gangurde dev->half_qpid_udma_shift = 31*f3bdbd42SAbhijit Gangurde order_base_2(dev->lif_cfg.qp_count / dev->lif_cfg.udma_count); 32*f3bdbd42SAbhijit Gangurde ionic_resid_init(&dev->inuse_dbid, dev->lif_cfg.dbid_count); 33*f3bdbd42SAbhijit Gangurde } 34*f3bdbd42SAbhijit Gangurde 35*f3bdbd42SAbhijit Gangurde static void ionic_destroy_resids(struct ionic_ibdev *dev) 36*f3bdbd42SAbhijit Gangurde { 37*f3bdbd42SAbhijit Gangurde ionic_resid_destroy(&dev->inuse_cqid); 38*f3bdbd42SAbhijit Gangurde ionic_resid_destroy(&dev->inuse_pdid); 39*f3bdbd42SAbhijit Gangurde ionic_resid_destroy(&dev->inuse_ahid); 40*f3bdbd42SAbhijit Gangurde ionic_resid_destroy(&dev->inuse_mrid); 41*f3bdbd42SAbhijit Gangurde ionic_resid_destroy(&dev->inuse_qpid); 42*f3bdbd42SAbhijit Gangurde ionic_resid_destroy(&dev->inuse_dbid); 43*f3bdbd42SAbhijit Gangurde } 44*f3bdbd42SAbhijit Gangurde 458d765af5SAbhijit Gangurde static void ionic_destroy_ibdev(struct ionic_ibdev *dev) 468d765af5SAbhijit Gangurde { 47*f3bdbd42SAbhijit Gangurde ionic_kill_rdma_admin(dev, false); 488d765af5SAbhijit Gangurde ib_unregister_device(&dev->ibdev); 49*f3bdbd42SAbhijit Gangurde ionic_destroy_rdma_admin(dev); 50*f3bdbd42SAbhijit Gangurde ionic_destroy_resids(dev); 51*f3bdbd42SAbhijit Gangurde WARN_ON(!xa_empty(&dev->cq_tbl)); 52*f3bdbd42SAbhijit Gangurde xa_destroy(&dev->cq_tbl); 538d765af5SAbhijit Gangurde ib_dealloc_device(&dev->ibdev); 548d765af5SAbhijit Gangurde } 558d765af5SAbhijit Gangurde 568d765af5SAbhijit Gangurde static struct ionic_ibdev *ionic_create_ibdev(struct ionic_aux_dev *ionic_adev) 578d765af5SAbhijit Gangurde { 588d765af5SAbhijit Gangurde struct ib_device *ibdev; 598d765af5SAbhijit Gangurde struct ionic_ibdev *dev; 608d765af5SAbhijit Gangurde struct net_device *ndev; 618d765af5SAbhijit Gangurde int rc; 628d765af5SAbhijit Gangurde 638d765af5SAbhijit Gangurde dev = ib_alloc_device(ionic_ibdev, ibdev); 648d765af5SAbhijit Gangurde if (!dev) 658d765af5SAbhijit Gangurde return ERR_PTR(-EINVAL); 668d765af5SAbhijit Gangurde 678d765af5SAbhijit Gangurde ionic_fill_lif_cfg(ionic_adev->lif, &dev->lif_cfg); 688d765af5SAbhijit Gangurde 69*f3bdbd42SAbhijit Gangurde xa_init_flags(&dev->cq_tbl, GFP_ATOMIC); 70*f3bdbd42SAbhijit Gangurde 71*f3bdbd42SAbhijit Gangurde ionic_init_resids(dev); 72*f3bdbd42SAbhijit Gangurde 73*f3bdbd42SAbhijit Gangurde rc = ionic_rdma_reset_devcmd(dev); 74*f3bdbd42SAbhijit Gangurde if (rc) 75*f3bdbd42SAbhijit Gangurde goto err_reset; 76*f3bdbd42SAbhijit Gangurde 77*f3bdbd42SAbhijit Gangurde rc = ionic_create_rdma_admin(dev); 78*f3bdbd42SAbhijit Gangurde if (rc) 79*f3bdbd42SAbhijit Gangurde goto err_admin; 80*f3bdbd42SAbhijit Gangurde 818d765af5SAbhijit Gangurde ibdev = &dev->ibdev; 828d765af5SAbhijit Gangurde ibdev->dev.parent = dev->lif_cfg.hwdev; 838d765af5SAbhijit Gangurde 848d765af5SAbhijit Gangurde strscpy(ibdev->name, "ionic_%d", IB_DEVICE_NAME_MAX); 858d765af5SAbhijit Gangurde strscpy(ibdev->node_desc, DEVICE_DESCRIPTION, IB_DEVICE_NODE_DESC_MAX); 868d765af5SAbhijit Gangurde 878d765af5SAbhijit Gangurde ibdev->node_type = RDMA_NODE_IB_CA; 888d765af5SAbhijit Gangurde ibdev->phys_port_cnt = 1; 898d765af5SAbhijit Gangurde 908d765af5SAbhijit Gangurde /* the first two eq are reserved for async events */ 918d765af5SAbhijit Gangurde ibdev->num_comp_vectors = dev->lif_cfg.eq_count - 2; 928d765af5SAbhijit Gangurde 938d765af5SAbhijit Gangurde ndev = ionic_lif_netdev(ionic_adev->lif); 948d765af5SAbhijit Gangurde addrconf_ifid_eui48((u8 *)&ibdev->node_guid, ndev); 958d765af5SAbhijit Gangurde rc = ib_device_set_netdev(ibdev, ndev, 1); 968d765af5SAbhijit Gangurde /* ionic_lif_netdev() returns ndev with refcount held */ 978d765af5SAbhijit Gangurde dev_put(ndev); 988d765af5SAbhijit Gangurde if (rc) 998d765af5SAbhijit Gangurde goto err_admin; 1008d765af5SAbhijit Gangurde 1018d765af5SAbhijit Gangurde rc = ib_register_device(ibdev, "ionic_%d", ibdev->dev.parent); 1028d765af5SAbhijit Gangurde if (rc) 1038d765af5SAbhijit Gangurde goto err_register; 1048d765af5SAbhijit Gangurde 1058d765af5SAbhijit Gangurde return dev; 1068d765af5SAbhijit Gangurde 1078d765af5SAbhijit Gangurde err_register: 1088d765af5SAbhijit Gangurde err_admin: 109*f3bdbd42SAbhijit Gangurde ionic_kill_rdma_admin(dev, false); 110*f3bdbd42SAbhijit Gangurde ionic_destroy_rdma_admin(dev); 111*f3bdbd42SAbhijit Gangurde err_reset: 112*f3bdbd42SAbhijit Gangurde ionic_destroy_resids(dev); 113*f3bdbd42SAbhijit Gangurde xa_destroy(&dev->cq_tbl); 1148d765af5SAbhijit Gangurde ib_dealloc_device(&dev->ibdev); 1158d765af5SAbhijit Gangurde 1168d765af5SAbhijit Gangurde return ERR_PTR(rc); 1178d765af5SAbhijit Gangurde } 1188d765af5SAbhijit Gangurde 1198d765af5SAbhijit Gangurde static int ionic_aux_probe(struct auxiliary_device *adev, 1208d765af5SAbhijit Gangurde const struct auxiliary_device_id *id) 1218d765af5SAbhijit Gangurde { 1228d765af5SAbhijit Gangurde struct ionic_aux_dev *ionic_adev; 1238d765af5SAbhijit Gangurde struct ionic_ibdev *dev; 1248d765af5SAbhijit Gangurde 1258d765af5SAbhijit Gangurde ionic_adev = container_of(adev, struct ionic_aux_dev, adev); 1268d765af5SAbhijit Gangurde dev = ionic_create_ibdev(ionic_adev); 1278d765af5SAbhijit Gangurde if (IS_ERR(dev)) 1288d765af5SAbhijit Gangurde return dev_err_probe(&adev->dev, PTR_ERR(dev), 1298d765af5SAbhijit Gangurde "Failed to register ibdev\n"); 1308d765af5SAbhijit Gangurde 1318d765af5SAbhijit Gangurde auxiliary_set_drvdata(adev, dev); 1328d765af5SAbhijit Gangurde ibdev_dbg(&dev->ibdev, "registered\n"); 1338d765af5SAbhijit Gangurde 1348d765af5SAbhijit Gangurde return 0; 1358d765af5SAbhijit Gangurde } 1368d765af5SAbhijit Gangurde 1378d765af5SAbhijit Gangurde static void ionic_aux_remove(struct auxiliary_device *adev) 1388d765af5SAbhijit Gangurde { 1398d765af5SAbhijit Gangurde struct ionic_ibdev *dev = auxiliary_get_drvdata(adev); 1408d765af5SAbhijit Gangurde 1418d765af5SAbhijit Gangurde dev_dbg(&adev->dev, "unregister ibdev\n"); 1428d765af5SAbhijit Gangurde ionic_destroy_ibdev(dev); 1438d765af5SAbhijit Gangurde dev_dbg(&adev->dev, "unregistered\n"); 1448d765af5SAbhijit Gangurde } 1458d765af5SAbhijit Gangurde 1468d765af5SAbhijit Gangurde static const struct auxiliary_device_id ionic_aux_id_table[] = { 1478d765af5SAbhijit Gangurde { .name = "ionic.rdma", }, 1488d765af5SAbhijit Gangurde {}, 1498d765af5SAbhijit Gangurde }; 1508d765af5SAbhijit Gangurde 1518d765af5SAbhijit Gangurde MODULE_DEVICE_TABLE(auxiliary, ionic_aux_id_table); 1528d765af5SAbhijit Gangurde 1538d765af5SAbhijit Gangurde static struct auxiliary_driver ionic_aux_r_driver = { 1548d765af5SAbhijit Gangurde .name = "rdma", 1558d765af5SAbhijit Gangurde .probe = ionic_aux_probe, 1568d765af5SAbhijit Gangurde .remove = ionic_aux_remove, 1578d765af5SAbhijit Gangurde .id_table = ionic_aux_id_table, 1588d765af5SAbhijit Gangurde }; 1598d765af5SAbhijit Gangurde 1608d765af5SAbhijit Gangurde static int __init ionic_mod_init(void) 1618d765af5SAbhijit Gangurde { 1628d765af5SAbhijit Gangurde int rc; 1638d765af5SAbhijit Gangurde 164*f3bdbd42SAbhijit Gangurde ionic_evt_workq = create_workqueue(DRIVER_NAME "-evt"); 165*f3bdbd42SAbhijit Gangurde if (!ionic_evt_workq) 166*f3bdbd42SAbhijit Gangurde return -ENOMEM; 167*f3bdbd42SAbhijit Gangurde 1688d765af5SAbhijit Gangurde rc = auxiliary_driver_register(&ionic_aux_r_driver); 1698d765af5SAbhijit Gangurde if (rc) 1708d765af5SAbhijit Gangurde goto err_aux; 1718d765af5SAbhijit Gangurde 1728d765af5SAbhijit Gangurde return 0; 1738d765af5SAbhijit Gangurde 1748d765af5SAbhijit Gangurde err_aux: 175*f3bdbd42SAbhijit Gangurde destroy_workqueue(ionic_evt_workq); 176*f3bdbd42SAbhijit Gangurde 1778d765af5SAbhijit Gangurde return rc; 1788d765af5SAbhijit Gangurde } 1798d765af5SAbhijit Gangurde 1808d765af5SAbhijit Gangurde static void __exit ionic_mod_exit(void) 1818d765af5SAbhijit Gangurde { 1828d765af5SAbhijit Gangurde auxiliary_driver_unregister(&ionic_aux_r_driver); 183*f3bdbd42SAbhijit Gangurde destroy_workqueue(ionic_evt_workq); 1848d765af5SAbhijit Gangurde } 1858d765af5SAbhijit Gangurde 1868d765af5SAbhijit Gangurde module_init(ionic_mod_init); 1878d765af5SAbhijit Gangurde module_exit(ionic_mod_exit); 188