From e26c48cf23a4940208c5d82fcb37d20df234092b Mon Sep 17 00:00:00 2001 From: Leon Romanovsky Date: Mon, 13 Jul 2026 07:41:25 -0400 Subject: [PATCH] RDMA/hfi1: Align probe error unwinding with device removal init_one() defers handling errors from hfi1_init() and hfi1_register_ib_device() to a combined block. This allows IB registration to run after device initialization has failed. Cleanup then depends on two unrelated error values. The late probe failure path also differs from the common teardown in remove_one(), even though both release the same initialized hardware and driver resources. Maintaining separate sequences obscures ownership and allows the paths to drift whenever initialization changes. Unwind at each failing stage and keep late probe teardown ordered like remove_one(), so partial initialization releases exactly the resources it owns and normal removal remains the reference cleanup flow. Link: https://patch.msgid.link/20260708-clean-init-one-hfi1-v1-13-b9e9641268a5@nvidia.com Signed-off-by: Leon Romanovsky --- drivers/infiniband/hw/hfi1/init.c | 45 +++++++++++-------------------- 1 file changed, 16 insertions(+), 29 deletions(-) diff --git a/drivers/infiniband/hw/hfi1/init.c b/drivers/infiniband/hw/hfi1/init.c index 9ed7c1ffc93c..f94d896e7212 100644 --- a/drivers/infiniband/hw/hfi1/init.c +++ b/drivers/infiniband/hw/hfi1/init.c @@ -1549,18 +1549,14 @@ static void postinit_cleanup(struct hfi1_devdata *dd) hfi1_dev_affinity_clean_up(dd); hfi1_pcie_ddcleanup(dd); - hfi1_pcie_cleanup(dd->pcidev); cleanup_device_data(dd); - - hfi1_free_devdata(dd); } static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { - int ret = 0, pidx, initfail; + int ret; struct hfi1_devdata *dd; - struct hfi1_pportdata *ppd; /* First, lock the non-writable module parameters */ HFI1_CAP_LOCK(); @@ -1627,34 +1623,19 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent) goto destroy_workqueues; /* error already printed */ /* do the generic initialization */ - initfail = hfi1_init(dd, 0); + ret = hfi1_init(dd, 0); + if (ret) + goto free_rx; ret = hfi1_register_ib_device(dd); + if (ret) + goto free_rx; /* * Now ready for use. this should be cleared whenever we * detect a reset, or initiate one. */ - if (!initfail && !ret) - dd->flags |= HFI1_INITTED; - - if (initfail || ret) { - msix_clean_up_interrupts(dd); - stop_timers(dd); - for (pidx = 0; pidx < dd->num_pports; ++pidx) { - hfi1_quiet_serdes(dd->pport + pidx); - ppd = dd->pport + pidx; - destroy_workqueue(ppd->hfi1_wq); - destroy_workqueue(ppd->link_wq); - } - if (!ret) - hfi1_unregister_ib_device(dd); - hfi1_free_rx(dd); - postinit_cleanup(dd); - if (initfail) - ret = initfail; - return ret; /* everything already cleaned */ - } + dd->flags |= HFI1_INITTED; ret = hfi1_device_create(dd); if (ret) @@ -1666,6 +1647,12 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent) return 0; +free_rx: + hfi1_free_rx(dd); + shutdown_device(dd); + stop_timers(dd); + postinit_cleanup(dd); + destroy_workqueues: destroy_workqueues(dd); free_devdata: @@ -1711,11 +1698,11 @@ static void remove_one(struct pci_dev *pdev) * clear dma engines, etc. */ shutdown_device(dd); - destroy_workqueues(dd); - stop_timers(dd); - postinit_cleanup(dd); + destroy_workqueues(dd); + hfi1_free_devdata(dd); + hfi1_pcie_cleanup(pdev); } static void shutdown_one(struct pci_dev *pdev)