xref: /linux/drivers/infiniband/hw/ionic/ionic_ibdev.c (revision f3bdbd42702c6b10ebe627828c76ef51c68e4355)
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