[PATCH] EDAC/i82975x: Balance PCI ownership on probe and module exit
From: Myeonghun Pak
Date: Mon Sep 14 2026 - 21:36:45 EST
i82975x_init_one() leaves its PCI enable reference behind on failure
and removal. Also, the fallback probe is never removed at module exit:
i82975x_registered is initialized to one and never changed.
Balance PCI enablement and track successful fallback initialization so
module exit removes controllers that are not bound to the PCI driver.
Only remember a normally probed device after successful initialization,
and release the saved device reference on both normal and fallback exit.
This issue was identified during our ongoing static-analysis research
while reviewing kernel code.
Fixes: 420390f06a5a ("drivers/edac: new i82975x driver")
Cc: stable@xxxxxxxxxxxxxxx
Assisted-by: LLM
Co-developed-by: Ijae Kim <ae878000@xxxxxxxxx>
Signed-off-by: Ijae Kim <ae878000@xxxxxxxxx>
Signed-off-by: Myeonghun Pak <mhun512@xxxxxxxxx>
---
drivers/edac/i82975x_edac.c | 13 +++++++++----
1 file changed, 9 insertions(+), 4 deletions(-)
diff --git a/drivers/edac/i82975x_edac.c b/drivers/edac/i82975x_edac.c
--- a/drivers/edac/i82975x_edac.c
+++ b/drivers/edac/i82975x_edac.c
@@ -233,7 +233,7 @@ static struct pci_dev *mci_pdev;
* already registered driver
*/
-static int i82975x_registered = 1;
+static bool i82975x_fallback;
static void i82975x_get_error_info(struct mem_ctl_info *mci,
struct i82975x_error_info *info)
@@ -597,6 +597,10 @@ static int i82975x_init_one(struct pci_dev *pdev,
return -EIO;
rc = i82975x_probe1(pdev, ent->driver_data);
+ if (rc) {
+ pci_disable_device(pdev);
+ return rc;
+ }
if (mci_pdev == NULL)
mci_pdev = pci_dev_get(pdev);
@@ -620,6 +624,7 @@ static void i82975x_remove_one(struct pci_dev *pdev)
iounmap( pvt->mch_window );
edac_mc_free(mci);
+ pci_disable_device(pdev);
}
static const struct pci_device_id i82975x_pci_tbl[] = {
@@ -670,6 +675,7 @@ static int __init i82975x_init(void)
pci_rc = -ENODEV;
goto fail1;
}
+ i82975x_fallback = true;
}
return 0;
@@ -688,10 +694,9 @@ static void __exit i82975x_exit(void)
pci_unregister_driver(&i82975x_driver);
- if (!i82975x_registered) {
+ if (i82975x_fallback)
i82975x_remove_one(mci_pdev);
- pci_dev_put(mci_pdev);
- }
+ pci_dev_put(mci_pdev);
}
module_init(i82975x_init);
--
2.51.0