diff options
| author | Zide Chen <zide.chen@intel.com> | 2026-06-11 09:00:26 -0700 |
|---|---|---|
| committer | Peter Zijlstra <peterz@infradead.org> | 2026-06-30 10:57:03 +0200 |
| commit | 003267cb94e21d762eb72d6977d84f44f1705bb7 (patch) | |
| tree | 6004d0234ce5bd1ca9c767dbb8ad72272d27aa86 | |
| parent | dc59e4fea9d83f03bad6bddf3fa2e52491777482 (diff) | |
| download | linux-003267cb94e21d762eb72d6977d84f44f1705bb7.tar.gz linux-003267cb94e21d762eb72d6977d84f44f1705bb7.zip | |
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@intel.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Dapeng Mi <dapeng1.mi@linux.intel.com>
Link: https://sashiko.dev/#/patchset/20260512233048.9577-1-zide.chen@intel.com?part=1
Link: https://patch.msgid.link/20260611160033.66760-2-zide.chen@intel.com
| -rw-r--r-- | arch/x86/events/intel/uncore.c | 5 |
1 files changed, 4 insertions, 1 deletions
diff --git a/arch/x86/events/intel/uncore.c b/arch/x86/events/intel/uncore.c index 7857959c6e82..b69b6a21d46b 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; } |
