[tip: perf/core] perf/x86/intel/uncore: Fix PCI PMU cleanup on setup failure
From: tip-bot2 for Zide Chen
Date: Tue Jun 30 2026 - 05:15:30 EST
The following commit has been merged into the perf/core branch of tip:
Commit-ID: 003267cb94e21d762eb72d6977d84f44f1705bb7
Gitweb: https://git.kernel.org/tip/003267cb94e21d762eb72d6977d84f44f1705bb7
Author: Zide Chen <zide.chen@xxxxxxxxx>
AuthorDate: Thu, 11 Jun 2026 09:00:26 -07:00
Committer: Peter Zijlstra <peterz@xxxxxxxxxxxxx>
CommitterDate: Tue, 30 Jun 2026 10:57:03 +02:00
perf/x86/intel/uncore: Fix PCI PMU cleanup on setup failure
When uncore_pci_pmu_register() fails, pmu->boxes[die] is set to NULL
before returning. In the uncore_pci_remove() path, this causes
uncore_pci_pmu_unregister() to be skipped entirely, leaking
pmu->activeboxes. In the uncore_bus_notify() path,
uncore_pci_pmu_unregister() may still be called and must exit early
when pmu->boxes[die] is NULL to avoid a NULL pointer dereference, and
to ensure activeboxes is only decremented for a previously active box.
Additionally, since pci_get_drvdata() returns NULL on registration
failure, uncore_pci_remove() can no longer treat NULL drvdata as an
indicator of an auxiliary PCI device. Remove the associated
WARN_ON_ONCE().
Signed-off-by: Zide Chen <zide.chen@xxxxxxxxx>
Signed-off-by: Peter Zijlstra (Intel) <peterz@xxxxxxxxxxxxx>
Reviewed-by: Dapeng Mi <dapeng1.mi@xxxxxxxxxxxxxxx>
Link: https://sashiko.dev/#/patchset/20260512233048.9577-1-zide.chen@xxxxxxxxx?part=1
Link: https://patch.msgid.link/20260611160033.66760-2-zide.chen@xxxxxxxxx
---
arch/x86/events/intel/uncore.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/arch/x86/events/intel/uncore.c b/arch/x86/events/intel/uncore.c
index 7857959..b69b6a2 100644
--- a/arch/x86/events/intel/uncore.c
+++ b/arch/x86/events/intel/uncore.c
@@ -1183,6 +1183,7 @@ static int uncore_pci_pmu_register(struct pci_dev *pdev,
/* First active box registers the pmu */
ret = uncore_pmu_register(pmu);
if (ret) {
+ atomic_dec(&pmu->activeboxes);
pmu->boxes[die] = NULL;
uncore_box_exit(box);
kfree(box);
@@ -1248,6 +1249,9 @@ static void uncore_pci_pmu_unregister(struct intel_uncore_pmu *pmu, int die)
{
struct intel_uncore_box *box = pmu->boxes[die];
+ if (!box)
+ return;
+
pmu->boxes[die] = NULL;
if (atomic_dec_return(&pmu->activeboxes) == 0)
uncore_pmu_unregister(pmu);
@@ -1272,7 +1276,6 @@ static void uncore_pci_remove(struct pci_dev *pdev)
break;
}
}
- WARN_ON_ONCE(i >= UNCORE_EXTRA_PCI_DEV_MAX);
return;
}