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 const struct ib_device_ops ionic_dev_ops = { 19 .owner = THIS_MODULE, 20 .driver_id = RDMA_DRIVER_IONIC, 21 .uverbs_abi_ver = IONIC_ABI_VERSION, 22 23 .alloc_ucontext = ionic_alloc_ucontext, 24 .dealloc_ucontext = ionic_dealloc_ucontext, 25 .mmap = ionic_mmap, 26 .mmap_free = ionic_mmap_free, 27 .alloc_pd = ionic_alloc_pd, 28 .dealloc_pd = ionic_dealloc_pd, 29 .create_ah = ionic_create_ah, 30 .query_ah = ionic_query_ah, 31 .destroy_ah = ionic_destroy_ah, 32 .create_user_ah = ionic_create_ah, 33 .get_dma_mr = ionic_get_dma_mr, 34 .reg_user_mr = ionic_reg_user_mr, 35 .reg_user_mr_dmabuf = ionic_reg_user_mr_dmabuf, 36 .dereg_mr = ionic_dereg_mr, 37 .alloc_mr = ionic_alloc_mr, 38 .map_mr_sg = ionic_map_mr_sg, 39 .alloc_mw = ionic_alloc_mw, 40 .dealloc_mw = ionic_dealloc_mw, 41 .create_cq = ionic_create_cq, 42 .destroy_cq = ionic_destroy_cq, 43 .create_qp = ionic_create_qp, 44 .modify_qp = ionic_modify_qp, 45 .query_qp = ionic_query_qp, 46 .destroy_qp = ionic_destroy_qp, 47 48 .post_send = ionic_post_send, 49 .post_recv = ionic_post_recv, 50 .poll_cq = ionic_poll_cq, 51 .req_notify_cq = ionic_req_notify_cq, 52 53 INIT_RDMA_OBJ_SIZE(ib_ucontext, ionic_ctx, ibctx), 54 INIT_RDMA_OBJ_SIZE(ib_pd, ionic_pd, ibpd), 55 INIT_RDMA_OBJ_SIZE(ib_ah, ionic_ah, ibah), 56 INIT_RDMA_OBJ_SIZE(ib_cq, ionic_vcq, ibcq), 57 INIT_RDMA_OBJ_SIZE(ib_qp, ionic_qp, ibqp), 58 INIT_RDMA_OBJ_SIZE(ib_mw, ionic_mr, ibmw), 59 }; 60 61 static void ionic_init_resids(struct ionic_ibdev *dev) 62 { 63 ionic_resid_init(&dev->inuse_cqid, dev->lif_cfg.cq_count); 64 dev->half_cqid_udma_shift = 65 order_base_2(dev->lif_cfg.cq_count / dev->lif_cfg.udma_count); 66 ionic_resid_init(&dev->inuse_pdid, IONIC_MAX_PD); 67 ionic_resid_init(&dev->inuse_ahid, dev->lif_cfg.nahs_per_lif); 68 ionic_resid_init(&dev->inuse_mrid, dev->lif_cfg.nmrs_per_lif); 69 /* skip reserved lkey */ 70 dev->next_mrkey = 1; 71 ionic_resid_init(&dev->inuse_qpid, dev->lif_cfg.qp_count); 72 /* skip reserved SMI and GSI qpids */ 73 dev->half_qpid_udma_shift = 74 order_base_2(dev->lif_cfg.qp_count / dev->lif_cfg.udma_count); 75 ionic_resid_init(&dev->inuse_dbid, dev->lif_cfg.dbid_count); 76 } 77 78 static void ionic_destroy_resids(struct ionic_ibdev *dev) 79 { 80 ionic_resid_destroy(&dev->inuse_cqid); 81 ionic_resid_destroy(&dev->inuse_pdid); 82 ionic_resid_destroy(&dev->inuse_ahid); 83 ionic_resid_destroy(&dev->inuse_mrid); 84 ionic_resid_destroy(&dev->inuse_qpid); 85 ionic_resid_destroy(&dev->inuse_dbid); 86 } 87 88 static void ionic_destroy_ibdev(struct ionic_ibdev *dev) 89 { 90 ionic_kill_rdma_admin(dev, false); 91 ib_unregister_device(&dev->ibdev); 92 ionic_destroy_rdma_admin(dev); 93 ionic_destroy_resids(dev); 94 WARN_ON(!xa_empty(&dev->qp_tbl)); 95 xa_destroy(&dev->qp_tbl); 96 WARN_ON(!xa_empty(&dev->cq_tbl)); 97 xa_destroy(&dev->cq_tbl); 98 ib_dealloc_device(&dev->ibdev); 99 } 100 101 static struct ionic_ibdev *ionic_create_ibdev(struct ionic_aux_dev *ionic_adev) 102 { 103 struct ib_device *ibdev; 104 struct ionic_ibdev *dev; 105 struct net_device *ndev; 106 int rc; 107 108 dev = ib_alloc_device(ionic_ibdev, ibdev); 109 if (!dev) 110 return ERR_PTR(-EINVAL); 111 112 ionic_fill_lif_cfg(ionic_adev->lif, &dev->lif_cfg); 113 114 xa_init_flags(&dev->qp_tbl, GFP_ATOMIC); 115 xa_init_flags(&dev->cq_tbl, GFP_ATOMIC); 116 117 ionic_init_resids(dev); 118 119 rc = ionic_rdma_reset_devcmd(dev); 120 if (rc) 121 goto err_reset; 122 123 rc = ionic_create_rdma_admin(dev); 124 if (rc) 125 goto err_admin; 126 127 ibdev = &dev->ibdev; 128 ibdev->dev.parent = dev->lif_cfg.hwdev; 129 130 strscpy(ibdev->name, "ionic_%d", IB_DEVICE_NAME_MAX); 131 strscpy(ibdev->node_desc, DEVICE_DESCRIPTION, IB_DEVICE_NODE_DESC_MAX); 132 133 ibdev->node_type = RDMA_NODE_IB_CA; 134 ibdev->phys_port_cnt = 1; 135 136 /* the first two eq are reserved for async events */ 137 ibdev->num_comp_vectors = dev->lif_cfg.eq_count - 2; 138 139 ndev = ionic_lif_netdev(ionic_adev->lif); 140 addrconf_ifid_eui48((u8 *)&ibdev->node_guid, ndev); 141 rc = ib_device_set_netdev(ibdev, ndev, 1); 142 /* ionic_lif_netdev() returns ndev with refcount held */ 143 dev_put(ndev); 144 if (rc) 145 goto err_admin; 146 147 ib_set_device_ops(&dev->ibdev, &ionic_dev_ops); 148 149 rc = ib_register_device(ibdev, "ionic_%d", ibdev->dev.parent); 150 if (rc) 151 goto err_register; 152 153 return dev; 154 155 err_register: 156 err_admin: 157 ionic_kill_rdma_admin(dev, false); 158 ionic_destroy_rdma_admin(dev); 159 err_reset: 160 ionic_destroy_resids(dev); 161 xa_destroy(&dev->qp_tbl); 162 xa_destroy(&dev->cq_tbl); 163 ib_dealloc_device(&dev->ibdev); 164 165 return ERR_PTR(rc); 166 } 167 168 static int ionic_aux_probe(struct auxiliary_device *adev, 169 const struct auxiliary_device_id *id) 170 { 171 struct ionic_aux_dev *ionic_adev; 172 struct ionic_ibdev *dev; 173 174 ionic_adev = container_of(adev, struct ionic_aux_dev, adev); 175 dev = ionic_create_ibdev(ionic_adev); 176 if (IS_ERR(dev)) 177 return dev_err_probe(&adev->dev, PTR_ERR(dev), 178 "Failed to register ibdev\n"); 179 180 auxiliary_set_drvdata(adev, dev); 181 ibdev_dbg(&dev->ibdev, "registered\n"); 182 183 return 0; 184 } 185 186 static void ionic_aux_remove(struct auxiliary_device *adev) 187 { 188 struct ionic_ibdev *dev = auxiliary_get_drvdata(adev); 189 190 dev_dbg(&adev->dev, "unregister ibdev\n"); 191 ionic_destroy_ibdev(dev); 192 dev_dbg(&adev->dev, "unregistered\n"); 193 } 194 195 static const struct auxiliary_device_id ionic_aux_id_table[] = { 196 { .name = "ionic.rdma", }, 197 {}, 198 }; 199 200 MODULE_DEVICE_TABLE(auxiliary, ionic_aux_id_table); 201 202 static struct auxiliary_driver ionic_aux_r_driver = { 203 .name = "rdma", 204 .probe = ionic_aux_probe, 205 .remove = ionic_aux_remove, 206 .id_table = ionic_aux_id_table, 207 }; 208 209 static int __init ionic_mod_init(void) 210 { 211 int rc; 212 213 ionic_evt_workq = create_workqueue(KBUILD_MODNAME "-evt"); 214 if (!ionic_evt_workq) 215 return -ENOMEM; 216 217 rc = auxiliary_driver_register(&ionic_aux_r_driver); 218 if (rc) 219 goto err_aux; 220 221 return 0; 222 223 err_aux: 224 destroy_workqueue(ionic_evt_workq); 225 226 return rc; 227 } 228 229 static void __exit ionic_mod_exit(void) 230 { 231 auxiliary_driver_unregister(&ionic_aux_r_driver); 232 destroy_workqueue(ionic_evt_workq); 233 } 234 235 module_init(ionic_mod_init); 236 module_exit(ionic_mod_exit); 237