1 // SPDX-License-Identifier: GPL-2.0 2 /* Copyright (C) 2018-2025, Advanced Micro Devices, Inc. */ 3 4 #include <linux/module.h> 5 #include <linux/printk.h> 6 #include <net/addrconf.h> 7 8 #include "ionic_ibdev.h" 9 10 #define DRIVER_DESCRIPTION "AMD Pensando RoCE HCA driver" 11 #define DEVICE_DESCRIPTION "AMD Pensando RoCE HCA" 12 13 MODULE_AUTHOR("Allen Hubbe <allen.hubbe@amd.com>"); 14 MODULE_DESCRIPTION(DRIVER_DESCRIPTION); 15 MODULE_LICENSE("GPL"); 16 MODULE_IMPORT_NS("NET_IONIC"); 17 18 static void ionic_init_resids(struct ionic_ibdev *dev) 19 { 20 ionic_resid_init(&dev->inuse_cqid, dev->lif_cfg.cq_count); 21 dev->half_cqid_udma_shift = 22 order_base_2(dev->lif_cfg.cq_count / dev->lif_cfg.udma_count); 23 ionic_resid_init(&dev->inuse_pdid, IONIC_MAX_PD); 24 ionic_resid_init(&dev->inuse_ahid, dev->lif_cfg.nahs_per_lif); 25 ionic_resid_init(&dev->inuse_mrid, dev->lif_cfg.nmrs_per_lif); 26 /* skip reserved lkey */ 27 dev->next_mrkey = 1; 28 ionic_resid_init(&dev->inuse_qpid, dev->lif_cfg.qp_count); 29 /* skip reserved SMI and GSI qpids */ 30 dev->half_qpid_udma_shift = 31 order_base_2(dev->lif_cfg.qp_count / dev->lif_cfg.udma_count); 32 ionic_resid_init(&dev->inuse_dbid, dev->lif_cfg.dbid_count); 33 } 34 35 static void ionic_destroy_resids(struct ionic_ibdev *dev) 36 { 37 ionic_resid_destroy(&dev->inuse_cqid); 38 ionic_resid_destroy(&dev->inuse_pdid); 39 ionic_resid_destroy(&dev->inuse_ahid); 40 ionic_resid_destroy(&dev->inuse_mrid); 41 ionic_resid_destroy(&dev->inuse_qpid); 42 ionic_resid_destroy(&dev->inuse_dbid); 43 } 44 45 static void ionic_destroy_ibdev(struct ionic_ibdev *dev) 46 { 47 ionic_kill_rdma_admin(dev, false); 48 ib_unregister_device(&dev->ibdev); 49 ionic_destroy_rdma_admin(dev); 50 ionic_destroy_resids(dev); 51 WARN_ON(!xa_empty(&dev->cq_tbl)); 52 xa_destroy(&dev->cq_tbl); 53 ib_dealloc_device(&dev->ibdev); 54 } 55 56 static struct ionic_ibdev *ionic_create_ibdev(struct ionic_aux_dev *ionic_adev) 57 { 58 struct ib_device *ibdev; 59 struct ionic_ibdev *dev; 60 struct net_device *ndev; 61 int rc; 62 63 dev = ib_alloc_device(ionic_ibdev, ibdev); 64 if (!dev) 65 return ERR_PTR(-EINVAL); 66 67 ionic_fill_lif_cfg(ionic_adev->lif, &dev->lif_cfg); 68 69 xa_init_flags(&dev->cq_tbl, GFP_ATOMIC); 70 71 ionic_init_resids(dev); 72 73 rc = ionic_rdma_reset_devcmd(dev); 74 if (rc) 75 goto err_reset; 76 77 rc = ionic_create_rdma_admin(dev); 78 if (rc) 79 goto err_admin; 80 81 ibdev = &dev->ibdev; 82 ibdev->dev.parent = dev->lif_cfg.hwdev; 83 84 strscpy(ibdev->name, "ionic_%d", IB_DEVICE_NAME_MAX); 85 strscpy(ibdev->node_desc, DEVICE_DESCRIPTION, IB_DEVICE_NODE_DESC_MAX); 86 87 ibdev->node_type = RDMA_NODE_IB_CA; 88 ibdev->phys_port_cnt = 1; 89 90 /* the first two eq are reserved for async events */ 91 ibdev->num_comp_vectors = dev->lif_cfg.eq_count - 2; 92 93 ndev = ionic_lif_netdev(ionic_adev->lif); 94 addrconf_ifid_eui48((u8 *)&ibdev->node_guid, ndev); 95 rc = ib_device_set_netdev(ibdev, ndev, 1); 96 /* ionic_lif_netdev() returns ndev with refcount held */ 97 dev_put(ndev); 98 if (rc) 99 goto err_admin; 100 101 rc = ib_register_device(ibdev, "ionic_%d", ibdev->dev.parent); 102 if (rc) 103 goto err_register; 104 105 return dev; 106 107 err_register: 108 err_admin: 109 ionic_kill_rdma_admin(dev, false); 110 ionic_destroy_rdma_admin(dev); 111 err_reset: 112 ionic_destroy_resids(dev); 113 xa_destroy(&dev->cq_tbl); 114 ib_dealloc_device(&dev->ibdev); 115 116 return ERR_PTR(rc); 117 } 118 119 static int ionic_aux_probe(struct auxiliary_device *adev, 120 const struct auxiliary_device_id *id) 121 { 122 struct ionic_aux_dev *ionic_adev; 123 struct ionic_ibdev *dev; 124 125 ionic_adev = container_of(adev, struct ionic_aux_dev, adev); 126 dev = ionic_create_ibdev(ionic_adev); 127 if (IS_ERR(dev)) 128 return dev_err_probe(&adev->dev, PTR_ERR(dev), 129 "Failed to register ibdev\n"); 130 131 auxiliary_set_drvdata(adev, dev); 132 ibdev_dbg(&dev->ibdev, "registered\n"); 133 134 return 0; 135 } 136 137 static void ionic_aux_remove(struct auxiliary_device *adev) 138 { 139 struct ionic_ibdev *dev = auxiliary_get_drvdata(adev); 140 141 dev_dbg(&adev->dev, "unregister ibdev\n"); 142 ionic_destroy_ibdev(dev); 143 dev_dbg(&adev->dev, "unregistered\n"); 144 } 145 146 static const struct auxiliary_device_id ionic_aux_id_table[] = { 147 { .name = "ionic.rdma", }, 148 {}, 149 }; 150 151 MODULE_DEVICE_TABLE(auxiliary, ionic_aux_id_table); 152 153 static struct auxiliary_driver ionic_aux_r_driver = { 154 .name = "rdma", 155 .probe = ionic_aux_probe, 156 .remove = ionic_aux_remove, 157 .id_table = ionic_aux_id_table, 158 }; 159 160 static int __init ionic_mod_init(void) 161 { 162 int rc; 163 164 ionic_evt_workq = create_workqueue(DRIVER_NAME "-evt"); 165 if (!ionic_evt_workq) 166 return -ENOMEM; 167 168 rc = auxiliary_driver_register(&ionic_aux_r_driver); 169 if (rc) 170 goto err_aux; 171 172 return 0; 173 174 err_aux: 175 destroy_workqueue(ionic_evt_workq); 176 177 return rc; 178 } 179 180 static void __exit ionic_mod_exit(void) 181 { 182 auxiliary_driver_unregister(&ionic_aux_r_driver); 183 destroy_workqueue(ionic_evt_workq); 184 } 185 186 module_init(ionic_mod_init); 187 module_exit(ionic_mod_exit); 188